fix: merge branch healthcare_refactor
This commit is contained in:
commit
b754faa59c
@ -108,9 +108,9 @@ class Account(NestedSet):
|
||||
parent_acc_name_map = {}
|
||||
parent_acc_name, parent_acc_number = frappe.db.get_value('Account', self.parent_account, \
|
||||
["account_name", "account_number"])
|
||||
filters = {
|
||||
filters = {
|
||||
"company": ["in", descendants],
|
||||
"account_name": parent_acc_name,
|
||||
"account_name": parent_acc_name,
|
||||
}
|
||||
if parent_acc_number:
|
||||
filters["account_number"] = parent_acc_number
|
||||
|
@ -21,7 +21,7 @@ class BankReconciliation(Document):
|
||||
|
||||
condition = ""
|
||||
if not self.include_reconciled_entries:
|
||||
condition = " and (clearance_date is null or clearance_date='0000-00-00')"
|
||||
condition = "and (clearance_date IS NULL or clearance_date='0000-00-00')"
|
||||
|
||||
journal_entries = frappe.db.sql("""
|
||||
select
|
||||
@ -34,12 +34,10 @@ class BankReconciliation(Document):
|
||||
where
|
||||
t2.parent = t1.name and t2.account = %(account)s and t1.docstatus=1
|
||||
and t1.posting_date >= %(from)s and t1.posting_date <= %(to)s
|
||||
and ifnull(t1.is_opening, 'No') = 'No' %(condition)s
|
||||
and ifnull(t1.is_opening, 'No') = 'No' {condition}
|
||||
group by t2.account, t1.name
|
||||
order by t1.posting_date ASC, t1.name DESC
|
||||
""", {"condition":condition, "account": self.account, "from": self.from_date, "to": self.to_date}, as_dict=1)
|
||||
|
||||
condition = ''
|
||||
""".format(condition=condition), {"account": self.account, "from": self.from_date, "to": self.to_date}, as_dict=1)
|
||||
|
||||
if self.bank_account:
|
||||
condition += 'and bank_account = %(bank_account)s'
|
||||
|
@ -17,17 +17,60 @@ frappe.ui.form.on('Chart of Accounts Importer', {
|
||||
if (frm.page && frm.page.show_import_button) {
|
||||
create_import_button(frm);
|
||||
}
|
||||
},
|
||||
|
||||
// show download template button when company is properly selected
|
||||
if(frm.doc.company) {
|
||||
// download the csv template file
|
||||
frm.add_custom_button(__("Download template"), function () {
|
||||
let get_template_url = 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template';
|
||||
open_url_post(frappe.request.url, { cmd: get_template_url, doctype: frm.doc.doctype });
|
||||
});
|
||||
} else {
|
||||
frm.set_value("import_file", "");
|
||||
}
|
||||
download_template: function(frm) {
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __("Download Template"),
|
||||
fields: [
|
||||
{
|
||||
label : "File Type",
|
||||
fieldname: "file_type",
|
||||
fieldtype: "Select",
|
||||
reqd: 1,
|
||||
options: ["Excel", "CSV"]
|
||||
},
|
||||
{
|
||||
label: "Template Type",
|
||||
fieldname: "template_type",
|
||||
fieldtype: "Select",
|
||||
reqd: 1,
|
||||
options: ["Sample Template", "Blank Template"],
|
||||
change: () => {
|
||||
let template_type = d.get_value('template_type');
|
||||
|
||||
if (template_type === "Sample Template") {
|
||||
d.set_df_property('template_type', 'description',
|
||||
`The Sample Template contains all the required accounts pre filled in the template.
|
||||
You can add more accounts or change existing accounts in the template as per your choice.`);
|
||||
} else {
|
||||
d.set_df_property('template_type', 'description',
|
||||
`The Blank Template contains just the account type and root type required to build the Chart
|
||||
of Accounts. Please enter the account names and add more rows as per your requirement.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
primary_action: function() {
|
||||
var data = d.get_values();
|
||||
|
||||
if (!data.template_type) {
|
||||
frappe.throw(__('Please select <b>Template Type</b> to download template'));
|
||||
}
|
||||
|
||||
open_url_post(
|
||||
'/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template',
|
||||
{
|
||||
file_type: data.file_type,
|
||||
template_type: data.template_type
|
||||
}
|
||||
);
|
||||
|
||||
d.hide();
|
||||
},
|
||||
primary_action_label: __('Download')
|
||||
});
|
||||
d.show();
|
||||
},
|
||||
|
||||
import_file: function (frm) {
|
||||
@ -41,21 +84,24 @@ frappe.ui.form.on('Chart of Accounts Importer', {
|
||||
},
|
||||
|
||||
company: function (frm) {
|
||||
// validate that no Gl Entry record for the company exists.
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_company",
|
||||
args: {
|
||||
company: frm.doc.company
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message===false) {
|
||||
frm.set_value("company", "");
|
||||
frappe.throw(__("Transactions against the company already exist! "));
|
||||
} else {
|
||||
frm.trigger("refresh");
|
||||
if (frm.doc.company) {
|
||||
// validate that no Gl Entry record for the company exists.
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_company",
|
||||
args: {
|
||||
company: frm.doc.company
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message===false) {
|
||||
frm.set_value("company", "");
|
||||
frappe.throw(__(`Transactions against the company already exist!
|
||||
Chart Of accounts can be imported for company with no transactions`));
|
||||
} else {
|
||||
frm.trigger("refresh");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -77,7 +123,7 @@ var validate_csv_data = function(frm) {
|
||||
};
|
||||
|
||||
var create_import_button = function(frm) {
|
||||
frm.page.set_primary_action(__("Start Import"), function () {
|
||||
frm.page.set_primary_action(__("Import"), function () {
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
|
||||
args: {
|
||||
@ -118,7 +164,8 @@ var generate_tree_preview = function(frm) {
|
||||
args: {
|
||||
file_name: frm.doc.import_file,
|
||||
parent: parent,
|
||||
doctype: 'Chart of Accounts Importer'
|
||||
doctype: 'Chart of Accounts Importer',
|
||||
file_type: frm.doc.file_type
|
||||
},
|
||||
onclick: function(node) {
|
||||
parent = node.value;
|
||||
|
@ -1,226 +1,71 @@
|
||||
{
|
||||
"allow_copy": 1,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2019-02-01 12:24:34.761380",
|
||||
"custom": 0,
|
||||
"actions": [],
|
||||
"allow_copy": 1,
|
||||
"creation": "2019-02-01 12:24:34.761380",
|
||||
"description": "Import Chart of Accounts from a csv file",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Other",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Other",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"company",
|
||||
"download_template",
|
||||
"import_file",
|
||||
"chart_preview",
|
||||
"chart_tree"
|
||||
],
|
||||
"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": 0,
|
||||
"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": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Company",
|
||||
"options": "Company"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "import_file_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,
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"depends_on": "company",
|
||||
"fieldname": "import_file",
|
||||
"fieldtype": "Attach",
|
||||
"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": "Attach custom Chart of Accounts file",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"label": "Attach custom Chart of Accounts file"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fieldname": "chart_preview",
|
||||
"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": "Chart Preview",
|
||||
"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": "Section Break",
|
||||
"label": "Chart Preview"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "chart_tree",
|
||||
"fieldtype": "HTML",
|
||||
"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": "Chart Tree",
|
||||
"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": "Chart Tree"
|
||||
},
|
||||
{
|
||||
"depends_on": "company",
|
||||
"fieldname": "download_template",
|
||||
"fieldtype": "Button",
|
||||
"label": "Download Template"
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 1,
|
||||
"hide_toolbar": 1,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 1,
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-02-04 23:10:30.136807",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Chart of Accounts Importer",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
"in_create": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2020-02-28 08:49:11.422846",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Chart of Accounts Importer",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"create": 1,
|
||||
"read": 1,
|
||||
"role": "Accounts Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 1,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -4,18 +4,28 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from functools import reduce
|
||||
import frappe, csv
|
||||
import frappe, csv, os
|
||||
from frappe import _
|
||||
from frappe.utils import cstr
|
||||
from frappe.utils import cstr, cint
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils.csvutils import UnicodeWriter
|
||||
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts, build_tree_from_json
|
||||
from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file, read_xls_file_from_attached_file
|
||||
|
||||
class ChartofAccountsImporter(Document):
|
||||
pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def validate_company(company):
|
||||
parent_company, allow_account_creation_against_child_company = frappe.db.get_value('Company',
|
||||
{'name': company}, ['parent_company',
|
||||
'allow_account_creation_against_child_company'])
|
||||
|
||||
if parent_company and (not allow_account_creation_against_child_company):
|
||||
frappe.throw(_("""{0} is a child company. Please import accounts against parent company
|
||||
or enable {1} in company master""").format(frappe.bold(company),
|
||||
frappe.bold('Allow Account Creation Against Child Company')), title='Wrong Company')
|
||||
|
||||
if frappe.db.get_all('GL Entry', {"company": company}, "name", limit=1):
|
||||
return False
|
||||
|
||||
@ -25,42 +35,85 @@ def import_coa(file_name, company):
|
||||
unset_existing_data(company)
|
||||
|
||||
# create accounts
|
||||
forest = build_forest(generate_data_from_csv(file_name))
|
||||
file_doc, extension = get_file(file_name)
|
||||
|
||||
if extension == 'csv':
|
||||
data = generate_data_from_csv(file_doc)
|
||||
else:
|
||||
data = generate_data_from_excel(file_doc, extension)
|
||||
|
||||
forest = build_forest(data)
|
||||
create_charts(company, custom_chart=forest)
|
||||
|
||||
# trigger on_update for company to reset default accounts
|
||||
set_default_accounts(company)
|
||||
|
||||
def generate_data_from_csv(file_name, as_dict=False):
|
||||
''' read csv file and return the generated nested tree '''
|
||||
if not file_name.endswith('.csv'):
|
||||
frappe.throw("Only CSV files can be used to for importing data. Please check the file format you are trying to upload")
|
||||
def get_file(file_name):
|
||||
file_doc = frappe.get_doc("File", {"file_url": file_name})
|
||||
parts = file_doc.get_extension()
|
||||
extension = parts[1]
|
||||
extension = extension.lstrip(".")
|
||||
|
||||
if extension not in ('csv', 'xlsx', 'xls'):
|
||||
frappe.throw("Only CSV and Excel files can be used to for importing data. Please check the file format you are trying to upload")
|
||||
|
||||
return file_doc, extension
|
||||
|
||||
def generate_data_from_csv(file_doc, as_dict=False):
|
||||
''' read csv file and return the generated nested tree '''
|
||||
|
||||
file_doc = frappe.get_doc('File', {"file_url": file_name})
|
||||
file_path = file_doc.get_full_path()
|
||||
|
||||
data = []
|
||||
with open(file_path, 'r') as in_file:
|
||||
csv_reader = list(csv.reader(in_file))
|
||||
headers = csv_reader[1][1:]
|
||||
del csv_reader[0:2] # delete top row and headers row
|
||||
headers = csv_reader[0]
|
||||
del csv_reader[0] # delete top row and headers row
|
||||
|
||||
for row in csv_reader:
|
||||
if as_dict:
|
||||
data.append({frappe.scrub(header): row[index+1] for index, header in enumerate(headers)})
|
||||
data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
|
||||
else:
|
||||
if not row[2]: row[2] = row[1]
|
||||
data.append(row[1:])
|
||||
if not row[1]: row[1] = row[0]
|
||||
data.append(row)
|
||||
|
||||
# convert csv data
|
||||
return data
|
||||
|
||||
def generate_data_from_excel(file_doc, extension, as_dict=False):
|
||||
content = file_doc.get_content()
|
||||
|
||||
if extension == "xlsx":
|
||||
rows = read_xlsx_file_from_attached_file(fcontent=content)
|
||||
elif extension == "xls":
|
||||
rows = read_xls_file_from_attached_file(content)
|
||||
|
||||
data = []
|
||||
headers = rows[0]
|
||||
del rows[0]
|
||||
|
||||
for row in rows:
|
||||
if as_dict:
|
||||
data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
|
||||
else:
|
||||
if not row[1]: row[1] = row[0]
|
||||
data.append(row)
|
||||
|
||||
return data
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_coa(doctype, parent, is_root=False, file_name=None):
|
||||
''' called by tree view (to fetch node's children) '''
|
||||
|
||||
file_doc, extension = get_file(file_name)
|
||||
parent = None if parent==_('All Accounts') else parent
|
||||
forest = build_forest(generate_data_from_csv(file_name))
|
||||
|
||||
if extension == 'csv':
|
||||
data = generate_data_from_csv(file_doc)
|
||||
else:
|
||||
data = generate_data_from_excel(file_doc, extension)
|
||||
|
||||
forest = build_forest(data)
|
||||
accounts = build_tree_from_json("", chart_data=forest) # returns alist of dict in a tree render-able form
|
||||
|
||||
# filter out to show data for the selected node only
|
||||
@ -91,6 +144,8 @@ def build_forest(data):
|
||||
|
||||
# returns the path of any node in list format
|
||||
def return_parent(data, child):
|
||||
from frappe import _
|
||||
|
||||
for row in data:
|
||||
account_name, parent_account = row[0:2]
|
||||
if parent_account == account_name == child:
|
||||
@ -98,8 +153,9 @@ def build_forest(data):
|
||||
elif account_name == child:
|
||||
parent_account_list = return_parent(data, parent_account)
|
||||
if not parent_account_list:
|
||||
frappe.throw(_("The parent account {0} does not exists")
|
||||
.format(parent_account))
|
||||
frappe.throw(_("The parent account {0} does not exists in the uploaded template").format(
|
||||
frappe.bold(parent_account)))
|
||||
|
||||
return [child] + parent_account_list
|
||||
|
||||
charts_map, paths = {}, []
|
||||
@ -114,7 +170,7 @@ def build_forest(data):
|
||||
error_messages.append("Row {0}: Please enter Account Name".format(line_no))
|
||||
|
||||
charts_map[account_name] = {}
|
||||
if is_group == 1: charts_map[account_name]["is_group"] = is_group
|
||||
if cint(is_group) == 1: charts_map[account_name]["is_group"] = is_group
|
||||
if account_type: charts_map[account_name]["account_type"] = account_type
|
||||
if root_type: charts_map[account_name]["root_type"] = root_type
|
||||
if account_number: charts_map[account_name]["account_number"] = account_number
|
||||
@ -132,24 +188,94 @@ def build_forest(data):
|
||||
|
||||
return out
|
||||
|
||||
def build_response_as_excel(writer):
|
||||
filename = frappe.generate_hash("", 10)
|
||||
with open(filename, 'wb') as f:
|
||||
f.write(cstr(writer.getvalue()).encode('utf-8'))
|
||||
f = open(filename)
|
||||
reader = csv.reader(f)
|
||||
|
||||
from frappe.utils.xlsxutils import make_xlsx
|
||||
xlsx_file = make_xlsx(reader, "Chart Of Accounts Importer Template")
|
||||
|
||||
f.close()
|
||||
os.remove(filename)
|
||||
|
||||
# write out response as a xlsx type
|
||||
frappe.response['filename'] = 'coa_importer_template.xlsx'
|
||||
frappe.response['filecontent'] = xlsx_file.getvalue()
|
||||
frappe.response['type'] = 'binary'
|
||||
|
||||
@frappe.whitelist()
|
||||
def download_template():
|
||||
def download_template(file_type, template_type):
|
||||
data = frappe._dict(frappe.local.form_dict)
|
||||
|
||||
writer = get_template(template_type)
|
||||
|
||||
if file_type == 'CSV':
|
||||
# download csv file
|
||||
frappe.response['result'] = cstr(writer.getvalue())
|
||||
frappe.response['type'] = 'csv'
|
||||
frappe.response['doctype'] = 'Chart of Accounts Importer'
|
||||
else:
|
||||
build_response_as_excel(writer)
|
||||
|
||||
def get_template(template_type):
|
||||
|
||||
fields = ["Account Name", "Parent Account", "Account Number", "Is Group", "Account Type", "Root Type"]
|
||||
writer = UnicodeWriter()
|
||||
writer.writerow(fields)
|
||||
|
||||
writer.writerow([_('Chart of Accounts Template')])
|
||||
writer.writerow([_("Column Labels : ")] + fields)
|
||||
writer.writerow([_("Start entering data from here : ")])
|
||||
if template_type == 'Blank Template':
|
||||
for root_type in get_root_types():
|
||||
writer.writerow(['', '', '', 1, '', root_type])
|
||||
|
||||
for account in get_mandatory_group_accounts():
|
||||
writer.writerow(['', '', '', 1, account, "Asset"])
|
||||
|
||||
for account_type in get_mandatory_account_types():
|
||||
writer.writerow(['', '', '', 0, account_type.get('account_type'), account_type.get('root_type')])
|
||||
else:
|
||||
writer = get_sample_template(writer)
|
||||
|
||||
return writer
|
||||
|
||||
def get_sample_template(writer):
|
||||
template = [
|
||||
["Application Of Funds(Assets)", "", "", 1, "", "Asset"],
|
||||
["Sources Of Funds(Liabilities)", "", "", 1, "", "Liability"],
|
||||
["Equity", "", "", 1, "", "Equity"],
|
||||
["Expenses", "", "", 1, "", "Expense"],
|
||||
["Income", "", "", 1, "", "Income"],
|
||||
["Bank Accounts", "Application Of Funds(Assets)", "", 1, "Bank", "Asset"],
|
||||
["Cash In Hand", "Application Of Funds(Assets)", "", 1, "Cash", "Asset"],
|
||||
["Stock Assets", "Application Of Funds(Assets)", "", 1, "Stock", "Asset"],
|
||||
["Cost Of Goods Sold", "Expenses", "", 0, "Cost of Goods Sold", "Expense"],
|
||||
["Asset Depreciation", "Expenses", "", 0, "Depreciation", "Expense"],
|
||||
["Fixed Assets", "Application Of Funds(Assets)", "", 0, "Fixed Asset", "Asset"],
|
||||
["Accounts Payable", "Sources Of Funds(Liabilities)", "", 0, "Payable", "Liability"],
|
||||
["Accounts Receivable", "Application Of Funds(Assets)", "", 1, "Receivable", "Asset"],
|
||||
["Stock Expenses", "Expenses", "", 0, "Stock Adjustment", "Expense"],
|
||||
["Sample Bank", "Bank Accounts", "", 0, "Bank", "Asset"],
|
||||
["Cash", "Cash In Hand", "", 0, "Cash", "Asset"],
|
||||
["Stores", "Stock Assets", "", 0, "Stock", "Asset"],
|
||||
]
|
||||
|
||||
for row in template:
|
||||
writer.writerow(row)
|
||||
|
||||
return writer
|
||||
|
||||
# download csv file
|
||||
frappe.response['result'] = cstr(writer.getvalue())
|
||||
frappe.response['type'] = 'csv'
|
||||
frappe.response['doctype'] = data.get('doctype')
|
||||
|
||||
@frappe.whitelist()
|
||||
def validate_accounts(file_name):
|
||||
accounts = generate_data_from_csv(file_name, as_dict=True)
|
||||
|
||||
file_doc, extension = get_file(file_name)
|
||||
|
||||
if extension == 'csv':
|
||||
accounts = generate_data_from_csv(file_doc, as_dict=True)
|
||||
else:
|
||||
accounts = generate_data_from_excel(file_doc, extension, as_dict=True)
|
||||
|
||||
accounts_dict = {}
|
||||
for account in accounts:
|
||||
@ -174,12 +300,38 @@ def validate_root(accounts):
|
||||
for account in roots:
|
||||
if not account.get("root_type") and account.get("account_name"):
|
||||
error_messages.append("Please enter Root Type for account- {0}".format(account.get("account_name")))
|
||||
elif account.get("root_type") not in ("Asset", "Liability", "Expense", "Income", "Equity") and account.get("account_name"):
|
||||
elif account.get("root_type") not in get_root_types() and account.get("account_name"):
|
||||
error_messages.append("Root Type for {0} must be one of the Asset, Liability, Income, Expense and Equity".format(account.get("account_name")))
|
||||
|
||||
if error_messages:
|
||||
return "<br>".join(error_messages)
|
||||
|
||||
def get_root_types():
|
||||
return ('Asset', 'Liability', 'Expense', 'Income', 'Equity')
|
||||
|
||||
def get_report_type(root_type):
|
||||
if root_type in ('Asset', 'Liability', 'Equity'):
|
||||
return 'Balance Sheet'
|
||||
else:
|
||||
return 'Profit and Loss'
|
||||
|
||||
def get_mandatory_group_accounts():
|
||||
return ('Bank', 'Cash', 'Stock')
|
||||
|
||||
def get_mandatory_account_types():
|
||||
return [
|
||||
{'account_type': 'Cost of Goods Sold', 'root_type': 'Expense'},
|
||||
{'account_type': 'Depreciation', 'root_type': 'Expense'},
|
||||
{'account_type': 'Fixed Asset', 'root_type': 'Asset'},
|
||||
{'account_type': 'Payable', 'root_type': 'Liability'},
|
||||
{'account_type': 'Receivable', 'root_type': 'Asset'},
|
||||
{'account_type': 'Stock Adjustment', 'root_type': 'Expense'},
|
||||
{'account_type': 'Bank', 'root_type': 'Asset'},
|
||||
{'account_type': 'Cash', 'root_type': 'Asset'},
|
||||
{'account_type': 'Stock', 'root_type': 'Asset'}
|
||||
]
|
||||
|
||||
|
||||
def validate_account_types(accounts):
|
||||
account_types_for_ledger = ["Cost of Goods Sold", "Depreciation", "Fixed Asset", "Payable", "Receivable", "Stock Adjustment"]
|
||||
account_types = [accounts[d]["account_type"] for d in accounts if not accounts[d]['is_group'] == 1]
|
||||
|
@ -18,7 +18,8 @@
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice",
|
||||
"options": "Sales Invoice",
|
||||
"reqd": 1
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "sales_invoice.customer",
|
||||
@ -60,7 +61,7 @@
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2019-09-26 11:05:36.016772",
|
||||
"modified": "2020-02-20 16:16:20.724620",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Discounted Invoice",
|
||||
|
@ -7,4 +7,4 @@ from __future__ import unicode_literals
|
||||
from frappe.model.document import Document
|
||||
|
||||
class DiscountedInvoice(Document):
|
||||
pass
|
||||
pass
|
@ -232,11 +232,36 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
|
||||
if bal < 0 and not on_cancel:
|
||||
frappe.throw(_("Outstanding for {0} cannot be less than zero ({1})").format(against_voucher, fmt_money(bal)))
|
||||
|
||||
# Update outstanding amt on against voucher
|
||||
if against_voucher_type in ["Sales Invoice", "Purchase Invoice", "Fees"]:
|
||||
update_outstanding_amt_in_ref(against_voucher, against_voucher_type, bal)
|
||||
|
||||
def update_outstanding_amt_in_ref(against_voucher, against_voucher_type, bal):
|
||||
data = []
|
||||
# Update outstanding amt on against voucher
|
||||
if against_voucher_type == "Fees":
|
||||
ref_doc = frappe.get_doc(against_voucher_type, against_voucher)
|
||||
ref_doc.db_set('outstanding_amount', bal)
|
||||
ref_doc.set_status(update=True)
|
||||
return
|
||||
elif against_voucher_type == "Purchase Invoice":
|
||||
from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import get_status
|
||||
data = frappe.db.get_value(against_voucher_type, against_voucher,
|
||||
["name as purchase_invoice", "outstanding_amount",
|
||||
"is_return", "due_date", "docstatus"])
|
||||
elif against_voucher_type == "Sales Invoice":
|
||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import get_status
|
||||
data = frappe.db.get_value(against_voucher_type, against_voucher,
|
||||
["name as sales_invoice", "outstanding_amount", "is_discounted",
|
||||
"is_return", "due_date", "docstatus"])
|
||||
|
||||
precision = frappe.get_precision(against_voucher_type, "outstanding_amount")
|
||||
data = list(data)
|
||||
data.append(precision)
|
||||
status = get_status(data)
|
||||
frappe.db.set_value(against_voucher_type, against_voucher, {
|
||||
'outstanding_amount': bal,
|
||||
'status': status
|
||||
})
|
||||
|
||||
def validate_frozen_account(account, adv_adj=None):
|
||||
frozen_account = frappe.db.get_value("Account", account, "freeze_account")
|
||||
@ -274,6 +299,9 @@ def update_against_account(voucher_type, voucher_no):
|
||||
if d.against != new_against:
|
||||
frappe.db.set_value("GL Entry", d.name, "against", new_against)
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("GL Entry", ["against_voucher_type", "against_voucher"])
|
||||
frappe.db.add_index("GL Entry", ["voucher_type", "voucher_no"])
|
||||
|
||||
def rename_gle_sle_docs():
|
||||
for doctype in ["GL Entry", "Stock Ledger Entry"]:
|
||||
|
@ -457,8 +457,7 @@ class JournalEntry(AccountsController):
|
||||
for d in self.get('accounts'):
|
||||
if d.party_type in ['Customer', 'Supplier'] and d.party:
|
||||
if not pay_to_recd_from:
|
||||
pay_to_recd_from = frappe.db.get_value(d.party_type, d.party,
|
||||
"customer_name" if d.party_type=="Customer" else "supplier_name")
|
||||
pay_to_recd_from = d.party
|
||||
|
||||
if pay_to_recd_from and pay_to_recd_from == d.party:
|
||||
party_amount += (d.debit_in_account_currency or d.credit_in_account_currency)
|
||||
@ -469,7 +468,8 @@ class JournalEntry(AccountsController):
|
||||
bank_account_currency = d.account_currency
|
||||
|
||||
if pay_to_recd_from:
|
||||
self.pay_to_recd_from = pay_to_recd_from
|
||||
self.pay_to_recd_from = frappe.db.get_value(d.party_type, pay_to_recd_from,
|
||||
"customer_name" if d.party_type=="Customer" else "supplier_name")
|
||||
if bank_amount:
|
||||
total_amount = bank_amount
|
||||
currency = bank_account_currency
|
||||
|
@ -149,6 +149,49 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", pi.name, "outstanding_amount"))
|
||||
self.assertEqual(outstanding_amount, 0)
|
||||
|
||||
|
||||
def test_payment_against_sales_invoice_to_check_status(self):
|
||||
si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
|
||||
currency="USD", conversion_rate=50)
|
||||
|
||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC")
|
||||
pe.reference_no = "1"
|
||||
pe.reference_date = "2016-01-01"
|
||||
pe.target_exchange_rate = 50
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
||||
self.assertEqual(outstanding_amount, 0)
|
||||
self.assertEqual(si.status, 'Paid')
|
||||
|
||||
pe.cancel()
|
||||
|
||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
||||
self.assertEqual(outstanding_amount, 100)
|
||||
self.assertEqual(si.status, 'Unpaid')
|
||||
|
||||
def test_payment_against_purchase_invoice_to_check_status(self):
|
||||
pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC",
|
||||
currency="USD", conversion_rate=50)
|
||||
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank USD - _TC")
|
||||
pe.reference_no = "1"
|
||||
pe.reference_date = "2016-01-01"
|
||||
pe.source_exchange_rate = 50
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
outstanding_amount = flt(frappe.db.get_value("Purchase Invoice", pi.name, "outstanding_amount"))
|
||||
self.assertEqual(outstanding_amount, 0)
|
||||
self.assertEqual(pi.status, 'Paid')
|
||||
|
||||
pe.cancel()
|
||||
|
||||
outstanding_amount = flt(frappe.db.get_value("Purchase Invoice", pi.name, "outstanding_amount"))
|
||||
self.assertEqual(outstanding_amount, 100)
|
||||
self.assertEqual(pi.status, 'Unpaid')
|
||||
|
||||
def test_payment_entry_against_ec(self):
|
||||
|
||||
payable = frappe.get_cached_value('Company', "_Test Company", 'default_payable_account')
|
||||
@ -566,4 +609,4 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
self.assertEqual(expected_party_account_balance, party_account_balance)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
accounts_settings.save()
|
@ -245,7 +245,7 @@ def filter_pricing_rules(args, pricing_rules, doc=None):
|
||||
|
||||
def validate_quantity_and_amount_for_suggestion(args, qty, amount, item_code, transaction_type):
|
||||
fieldname, msg = '', ''
|
||||
type_of_transaction = 'purcahse' if transaction_type == "buying" else "sale"
|
||||
type_of_transaction = 'purchase' if transaction_type == 'buying' else 'sale'
|
||||
|
||||
for field, value in {'min_qty': qty, 'min_amt': amount}.items():
|
||||
if (args.get(field) and value < args.get(field)
|
||||
@ -465,7 +465,7 @@ def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None):
|
||||
|
||||
item_details.free_item_data.update(item_data)
|
||||
item_details.free_item_data['uom'] = pricing_rule.free_item_uom or item_data.stock_uom
|
||||
item_details.free_item_data['conversion_factor'] = get_conversion_factor(free_item,
|
||||
item_details.free_item_data['conversion_factor'] = get_conversion_factor(free_item,
|
||||
item_details.free_item_data['uom']).get("conversion_factor", 1)
|
||||
|
||||
if item_details.get("parenttype") == 'Purchase Order':
|
||||
@ -508,7 +508,7 @@ def validate_coupon_code(coupon_name):
|
||||
frappe.throw(_("Sorry,coupon code validity has not started"))
|
||||
elif coupon.valid_upto:
|
||||
if coupon.valid_upto < getdate(today()) :
|
||||
frappe.throw(_("Sorry,coupon code validity has expired"))
|
||||
frappe.throw(_("Sorry,coupon code validity has expired"))
|
||||
elif coupon.used>=coupon.maximum_use:
|
||||
frappe.throw(_("Sorry,coupon code are exhausted"))
|
||||
else:
|
||||
|
@ -125,6 +125,27 @@ class PurchaseInvoice(BuyingController):
|
||||
else:
|
||||
self.remarks = _("No Remarks")
|
||||
|
||||
def set_status(self, update=False, status=None, update_modified=True):
|
||||
if self.is_new():
|
||||
if self.get('amended_from'):
|
||||
self.status = 'Draft'
|
||||
return
|
||||
|
||||
if not status:
|
||||
precision = self.precision("outstanding_amount")
|
||||
args = [
|
||||
self.name,
|
||||
self.outstanding_amount,
|
||||
self.is_return,
|
||||
self.due_date,
|
||||
self.docstatus,
|
||||
precision
|
||||
]
|
||||
self.status = get_status(args)
|
||||
|
||||
if update:
|
||||
self.db_set('status', self.status, update_modified = update_modified)
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
if not self.credit_to:
|
||||
self.credit_to = get_party_account("Supplier", self.supplier, self.company)
|
||||
@ -380,7 +401,7 @@ class PurchaseInvoice(BuyingController):
|
||||
update_outstanding_amt(self.credit_to, "Supplier", self.supplier,
|
||||
self.doctype, self.return_against if cint(self.is_return) and self.return_against else self.name)
|
||||
|
||||
if repost_future_gle and cint(self.update_stock) and self.auto_accounting_for_stock:
|
||||
if (repost_future_gle or self.flags.repost_future_gle) and cint(self.update_stock) and self.auto_accounting_for_stock:
|
||||
from erpnext.controllers.stock_controller import update_gl_entries_after
|
||||
items, warehouses = self.get_items_and_warehouses()
|
||||
update_gl_entries_after(self.posting_date, self.posting_time,
|
||||
@ -1007,6 +1028,34 @@ class PurchaseInvoice(BuyingController):
|
||||
# calculate totals again after applying TDS
|
||||
self.calculate_taxes_and_totals()
|
||||
|
||||
def get_status(*args):
|
||||
purchase_invoice, outstanding_amount, is_return, due_date, docstatus, precision = args[0]
|
||||
|
||||
outstanding_amount = flt(outstanding_amount, precision)
|
||||
due_date = getdate(due_date)
|
||||
now_date = getdate()
|
||||
|
||||
if docstatus == 2:
|
||||
status = "Cancelled"
|
||||
elif docstatus == 1:
|
||||
if outstanding_amount > 0 and due_date < now_date:
|
||||
status = "Overdue"
|
||||
elif outstanding_amount > 0 and due_date >= now_date:
|
||||
status = "Unpaid"
|
||||
#Check if outstanding amount is 0 due to debit note issued against invoice
|
||||
elif outstanding_amount <= 0 and is_return == 0 and frappe.db.get_value('Purchase Invoice', {'is_return': 1, 'return_against': purchase_invoice, 'docstatus': 1}):
|
||||
status = "Debit Note Issued"
|
||||
elif is_return == 1:
|
||||
status = "Return"
|
||||
elif outstanding_amount <=0:
|
||||
status = "Paid"
|
||||
else:
|
||||
status = "Submitted"
|
||||
else:
|
||||
status = "Draft"
|
||||
|
||||
return status
|
||||
|
||||
def get_list_context(context=None):
|
||||
from erpnext.controllers.website_list_for_contact import get_list_context
|
||||
list_context = get_list_context(context)
|
||||
|
@ -723,7 +723,7 @@ class SalesInvoice(SellingController):
|
||||
update_outstanding_amt(self.debit_to, "Customer", self.customer,
|
||||
self.doctype, self.return_against if cint(self.is_return) and self.return_against else self.name)
|
||||
|
||||
if repost_future_gle and cint(self.update_stock) \
|
||||
if (repost_future_gle or self.flags.repost_future_gle) and cint(self.update_stock) \
|
||||
and cint(auto_accounting_for_stock):
|
||||
items, warehouses = self.get_items_and_warehouses()
|
||||
update_gl_entries_after(self.posting_date, self.posting_time,
|
||||
@ -1217,63 +1217,84 @@ class SalesInvoice(SellingController):
|
||||
|
||||
self.set_missing_values(for_validate = True)
|
||||
|
||||
def get_discounting_status(self):
|
||||
status = None
|
||||
if self.is_discounted:
|
||||
invoice_discounting_list = frappe.db.sql("""
|
||||
select status
|
||||
from `tabInvoice Discounting` id, `tabDiscounted Invoice` d
|
||||
where
|
||||
id.name = d.parent
|
||||
and d.sales_invoice=%s
|
||||
and id.docstatus=1
|
||||
and status in ('Disbursed', 'Settled')
|
||||
""", self.name)
|
||||
for d in invoice_discounting_list:
|
||||
status = d[0]
|
||||
if status == "Disbursed":
|
||||
break
|
||||
return status
|
||||
|
||||
def set_status(self, update=False, status=None, update_modified=True):
|
||||
if self.is_new():
|
||||
if self.get('amended_from'):
|
||||
self.status = 'Draft'
|
||||
return
|
||||
|
||||
precision = self.precision("outstanding_amount")
|
||||
outstanding_amount = flt(self.outstanding_amount, precision)
|
||||
due_date = getdate(self.due_date)
|
||||
nowdate = getdate()
|
||||
discountng_status = self.get_discounting_status()
|
||||
|
||||
if not status:
|
||||
if self.docstatus == 2:
|
||||
status = "Cancelled"
|
||||
elif self.docstatus == 1:
|
||||
if outstanding_amount > 0 and due_date < nowdate and self.is_discounted and discountng_status=='Disbursed':
|
||||
self.status = "Overdue and Discounted"
|
||||
elif outstanding_amount > 0 and due_date < nowdate:
|
||||
self.status = "Overdue"
|
||||
elif outstanding_amount > 0 and due_date >= nowdate and self.is_discounted and discountng_status=='Disbursed':
|
||||
self.status = "Unpaid and Discounted"
|
||||
elif outstanding_amount > 0 and due_date >= nowdate:
|
||||
self.status = "Unpaid"
|
||||
#Check if outstanding amount is 0 due to credit note issued against invoice
|
||||
elif outstanding_amount <= 0 and self.is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}):
|
||||
self.status = "Credit Note Issued"
|
||||
elif self.is_return == 1:
|
||||
self.status = "Return"
|
||||
elif outstanding_amount<=0:
|
||||
self.status = "Paid"
|
||||
else:
|
||||
self.status = "Submitted"
|
||||
else:
|
||||
self.status = "Draft"
|
||||
precision = self.precision("outstanding_amount")
|
||||
args = [
|
||||
self.name,
|
||||
self.outstanding_amount,
|
||||
self.is_discounted,
|
||||
self.is_return,
|
||||
self.due_date,
|
||||
self.docstatus,
|
||||
precision,
|
||||
]
|
||||
self.status = get_status(args)
|
||||
|
||||
if update:
|
||||
self.db_set('status', self.status, update_modified = update_modified)
|
||||
|
||||
def get_discounting_status(sales_invoice):
|
||||
status = None
|
||||
|
||||
invoice_discounting_list = frappe.db.sql("""
|
||||
select status
|
||||
from `tabInvoice Discounting` id, `tabDiscounted Invoice` d
|
||||
where
|
||||
id.name = d.parent
|
||||
and d.sales_invoice=%s
|
||||
and id.docstatus=1
|
||||
and status in ('Disbursed', 'Settled')
|
||||
""", sales_invoice)
|
||||
|
||||
for d in invoice_discounting_list:
|
||||
status = d[0]
|
||||
if status == "Disbursed":
|
||||
break
|
||||
|
||||
return status
|
||||
|
||||
def get_status(*args):
|
||||
sales_invoice, outstanding_amount, is_discounted, is_return, due_date, docstatus, precision = args[0]
|
||||
|
||||
discounting_status = None
|
||||
if is_discounted:
|
||||
discounting_status = get_discounting_status(sales_invoice)
|
||||
|
||||
outstanding_amount = flt(outstanding_amount, precision)
|
||||
due_date = getdate(due_date)
|
||||
now_date = getdate()
|
||||
|
||||
if docstatus == 2:
|
||||
status = "Cancelled"
|
||||
elif docstatus == 1:
|
||||
if outstanding_amount > 0 and due_date < now_date and is_discounted and discounting_status=='Disbursed':
|
||||
status = "Overdue and Discounted"
|
||||
elif outstanding_amount > 0 and due_date < now_date:
|
||||
status = "Overdue"
|
||||
elif outstanding_amount > 0 and due_date >= now_date and is_discounted and discounting_status=='Disbursed':
|
||||
status = "Unpaid and Discounted"
|
||||
elif outstanding_amount > 0 and due_date >= now_date:
|
||||
status = "Unpaid"
|
||||
#Check if outstanding amount is 0 due to credit note issued against invoice
|
||||
elif outstanding_amount <= 0 and is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': sales_invoice, 'docstatus': 1}):
|
||||
status = "Credit Note Issued"
|
||||
elif is_return == 1:
|
||||
status = "Return"
|
||||
elif outstanding_amount <=0:
|
||||
status = "Paid"
|
||||
else:
|
||||
status = "Submitted"
|
||||
else:
|
||||
status = "Draft"
|
||||
|
||||
return status
|
||||
|
||||
def validate_inter_company_party(doctype, party, company, inter_company_reference):
|
||||
if not party:
|
||||
return
|
||||
|
@ -140,8 +140,11 @@ def make_entry(args, adv_adj, update_outstanding, from_repost=False):
|
||||
gle = frappe.get_doc(args)
|
||||
gle.flags.ignore_permissions = 1
|
||||
gle.flags.from_repost = from_repost
|
||||
gle.insert()
|
||||
gle.validate()
|
||||
gle.flags.ignore_permissions = True
|
||||
gle.db_insert()
|
||||
gle.run_method("on_update_with_args", adv_adj, update_outstanding, from_repost)
|
||||
gle.flags.ignore_validate = True
|
||||
gle.submit()
|
||||
|
||||
def validate_account_for_perpetual_inventory(gl_map):
|
||||
|
@ -11,18 +11,18 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
"reqd": 1,
|
||||
"default": frappe.defaults.get_user_default("Company")
|
||||
},
|
||||
{
|
||||
"fieldname":"report_date",
|
||||
"label": __("Posting Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
},
|
||||
{
|
||||
"fieldname":"ageing_based_on",
|
||||
"label": __("Ageing Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": 'Posting Date\nDue Date\nSupplier Invoice Date',
|
||||
"default": "Posting Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"report_date",
|
||||
"label": __("As on Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
"default": "Due Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"range1",
|
||||
|
@ -10,18 +10,18 @@ frappe.query_reports["Accounts Payable Summary"] = {
|
||||
"options": "Company",
|
||||
"default": frappe.defaults.get_user_default("Company")
|
||||
},
|
||||
{
|
||||
"fieldname":"report_date",
|
||||
"label": __("Posting Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
},
|
||||
{
|
||||
"fieldname":"ageing_based_on",
|
||||
"label": __("Ageing Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": 'Posting Date\nDue Date',
|
||||
"default": "Posting Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"report_date",
|
||||
"label": __("Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
"default": "Due Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"range1",
|
||||
|
@ -11,18 +11,18 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
"reqd": 1,
|
||||
"default": frappe.defaults.get_user_default("Company")
|
||||
},
|
||||
{
|
||||
"fieldname":"report_date",
|
||||
"label": __("Posting Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
},
|
||||
{
|
||||
"fieldname":"ageing_based_on",
|
||||
"label": __("Ageing Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": 'Posting Date\nDue Date',
|
||||
"default": "Posting Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"report_date",
|
||||
"label": __("As on Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
"default": "Due Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"range1",
|
||||
@ -148,7 +148,7 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
},
|
||||
{
|
||||
"fieldname":"show_delivery_notes",
|
||||
"label": __("Show Delivery Notes"),
|
||||
"label": __("Show Linked Delivery Notes"),
|
||||
"fieldtype": "Check",
|
||||
},
|
||||
{
|
||||
|
@ -10,18 +10,18 @@ frappe.query_reports["Accounts Receivable Summary"] = {
|
||||
"options": "Company",
|
||||
"default": frappe.defaults.get_user_default("Company")
|
||||
},
|
||||
{
|
||||
"fieldname":"report_date",
|
||||
"label": __("Posting Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
},
|
||||
{
|
||||
"fieldname":"ageing_based_on",
|
||||
"label": __("Ageing Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": 'Posting Date\nDue Date',
|
||||
"default": "Posting Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"report_date",
|
||||
"label": __("Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today()
|
||||
"default": "Due Date"
|
||||
},
|
||||
{
|
||||
"fieldname":"range1",
|
||||
|
@ -29,7 +29,7 @@ def get_data(filters):
|
||||
|
||||
row.update(next(asset for asset in assets if asset["asset_category"] == asset_category.get("asset_category", "")))
|
||||
row.accumulated_depreciation_as_on_to_date = (flt(row.accumulated_depreciation_as_on_from_date) +
|
||||
flt(row.depreciation_amount_during_the_period) - flt(row.depreciation_eliminated))
|
||||
flt(row.depreciation_amount_during_the_period) - flt(row.depreciation_eliminated_during_the_period))
|
||||
|
||||
row.net_asset_value_as_on_from_date = (flt(row.cost_as_on_from_date) -
|
||||
flt(row.accumulated_depreciation_as_on_from_date))
|
||||
@ -86,7 +86,6 @@ def get_asset_categories(filters):
|
||||
group by asset_category
|
||||
""", {"to_date": filters.to_date, "from_date": filters.from_date, "company": filters.company}, as_dict=1)
|
||||
|
||||
|
||||
def get_assets(filters):
|
||||
return frappe.db.sql("""
|
||||
SELECT results.asset_category,
|
||||
@ -94,9 +93,7 @@ def get_assets(filters):
|
||||
sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
|
||||
sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
|
||||
from (SELECT a.asset_category,
|
||||
ifnull(sum(a.opening_accumulated_depreciation +
|
||||
case when ds.schedule_date < %(from_date)s and
|
||||
(ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s) then
|
||||
ifnull(sum(case when ds.schedule_date < %(from_date)s then
|
||||
ds.depreciation_amount
|
||||
else
|
||||
0
|
||||
@ -107,7 +104,6 @@ def get_assets(filters):
|
||||
else
|
||||
0
|
||||
end), 0) as depreciation_eliminated_during_the_period,
|
||||
|
||||
ifnull(sum(case when ds.schedule_date >= %(from_date)s and ds.schedule_date <= %(to_date)s
|
||||
and (ifnull(a.disposal_date, 0) = 0 or ds.schedule_date <= a.disposal_date) then
|
||||
ds.depreciation_amount
|
||||
@ -120,7 +116,8 @@ def get_assets(filters):
|
||||
union
|
||||
SELECT a.asset_category,
|
||||
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0
|
||||
and (a.disposal_date < %(from_date)s or a.disposal_date > %(to_date)s) then
|
||||
and (a.disposal_date < %(from_date)s or a.disposal_date > %(to_date)s)
|
||||
then
|
||||
0
|
||||
else
|
||||
a.opening_accumulated_depreciation
|
||||
@ -133,7 +130,6 @@ def get_assets(filters):
|
||||
0 as depreciation_amount_during_the_period
|
||||
from `tabAsset` a
|
||||
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s
|
||||
and not exists(select * from `tabDepreciation Schedule` ds where a.name = ds.parent)
|
||||
group by a.asset_category) as results
|
||||
group by results.asset_category
|
||||
""", {"to_date": filters.to_date, "from_date": filters.from_date, "company": filters.company}, as_dict=1)
|
||||
|
@ -306,10 +306,6 @@ def get_conditions(filters):
|
||||
|
||||
def get_items(filters, additional_query_columns):
|
||||
conditions = get_conditions(filters)
|
||||
match_conditions = frappe.build_match_conditions("Purchase Invoice")
|
||||
|
||||
if match_conditions:
|
||||
match_conditions = " and {0} ".format(match_conditions)
|
||||
|
||||
if additional_query_columns:
|
||||
additional_query_columns = ', ' + ', '.join(additional_query_columns)
|
||||
@ -327,8 +323,8 @@ def get_items(filters, additional_query_columns):
|
||||
`tabPurchase Invoice`.supplier_name, `tabPurchase Invoice`.mode_of_payment {0}
|
||||
from `tabPurchase Invoice`, `tabPurchase Invoice Item`
|
||||
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and
|
||||
`tabPurchase Invoice`.docstatus = 1 %s %s
|
||||
""".format(additional_query_columns) % (conditions, match_conditions), filters, as_dict=1)
|
||||
`tabPurchase Invoice`.docstatus = 1 %s
|
||||
""".format(additional_query_columns) % (conditions), filters, as_dict=1)
|
||||
|
||||
def get_aii_accounts():
|
||||
return dict(frappe.db.sql("select name, stock_received_but_not_billed from tabCompany"))
|
||||
|
@ -119,7 +119,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
||||
add_sub_total_row(total_row, total_row_map, 'total_row', tax_columns)
|
||||
data.append(total_row_map.get('total_row'))
|
||||
skip_total_row = 1
|
||||
|
||||
|
||||
return columns, data, None, None, None, skip_total_row
|
||||
|
||||
def get_columns(additional_table_columns, filters):
|
||||
@ -370,10 +370,6 @@ def get_group_by_conditions(filters, doctype):
|
||||
|
||||
def get_items(filters, additional_query_columns):
|
||||
conditions = get_conditions(filters)
|
||||
match_conditions = frappe.build_match_conditions("Sales Invoice")
|
||||
|
||||
if match_conditions:
|
||||
match_conditions = " and {0} ".format(match_conditions)
|
||||
|
||||
if additional_query_columns:
|
||||
additional_query_columns = ', ' + ', '.join(additional_query_columns)
|
||||
@ -394,8 +390,8 @@ def get_items(filters, additional_query_columns):
|
||||
`tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {0}
|
||||
from `tabSales Invoice`, `tabSales Invoice Item`
|
||||
where `tabSales Invoice`.name = `tabSales Invoice Item`.parent
|
||||
and `tabSales Invoice`.docstatus = 1 {1} {2}
|
||||
""".format(additional_query_columns or '', conditions, match_conditions), filters, as_dict=1) #nosec
|
||||
and `tabSales Invoice`.docstatus = 1 {1}
|
||||
""".format(additional_query_columns or '', conditions), filters, as_dict=1) #nosec
|
||||
|
||||
def get_delivery_notes_against_sales_order(item_list):
|
||||
so_dn_map = frappe._dict()
|
||||
|
@ -12,7 +12,6 @@ from erpnext.stock.doctype.item.item import validate_end_of_life
|
||||
|
||||
def update_last_purchase_rate(doc, is_submit):
|
||||
"""updates last_purchase_rate in item table for each item"""
|
||||
|
||||
import frappe.utils
|
||||
this_purchase_date = frappe.utils.getdate(doc.get('posting_date') or doc.get('transaction_date'))
|
||||
|
||||
@ -23,7 +22,7 @@ def update_last_purchase_rate(doc, is_submit):
|
||||
# compare last purchase date and this transaction's date
|
||||
last_purchase_rate = None
|
||||
if last_purchase_details and \
|
||||
(last_purchase_details.purchase_date > this_purchase_date):
|
||||
(doc.get('docstatus') == 2 or last_purchase_details.purchase_date > this_purchase_date):
|
||||
last_purchase_rate = last_purchase_details['base_net_rate']
|
||||
elif is_submit == 1:
|
||||
# even if this transaction is the latest one, it should be submitted
|
||||
|
@ -7,6 +7,13 @@ def get_data():
|
||||
"label": _("Purchasing"),
|
||||
"icon": "fa fa-star",
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Material Request",
|
||||
"onboard": 1,
|
||||
"dependencies": ["Item"],
|
||||
"description": _("Request for purchase."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Purchase Order",
|
||||
@ -20,13 +27,6 @@ def get_data():
|
||||
"onboard": 1,
|
||||
"dependencies": ["Item", "Supplier"]
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Material Request",
|
||||
"onboard": 1,
|
||||
"dependencies": ["Item"],
|
||||
"description": _("Request for purchase."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Request for Quotation",
|
||||
@ -63,6 +63,11 @@ def get_data():
|
||||
"name": "Price List",
|
||||
"description": _("Price List master.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Pricing Rule",
|
||||
"description": _("Rules for applying pricing and discount.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Product Bundle",
|
||||
@ -80,11 +85,6 @@ def get_data():
|
||||
"type": "doctype",
|
||||
"name": "Promotional Scheme",
|
||||
"description": _("Rules for applying different promotional schemes.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Pricing Rule",
|
||||
"description": _("Rules for applying pricing and discount.")
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -149,13 +149,6 @@ def get_data():
|
||||
"reference_doctype": "Purchase Order",
|
||||
"onboard": 1
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Supplier-Wise Sales Analytics",
|
||||
"reference_doctype": "Stock Ledger Entry",
|
||||
"onboard": 1
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
@ -177,6 +170,16 @@ def get_data():
|
||||
"reference_doctype": "Material Request",
|
||||
"onboard": 1,
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Address And Contacts",
|
||||
"label": _("Supplier Addresses And Contacts"),
|
||||
"reference_doctype": "Address",
|
||||
"route_options": {
|
||||
"party_type": "Supplier"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -226,18 +229,15 @@ def get_data():
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Material Requests for which Supplier Quotations are not created",
|
||||
"reference_doctype": "Material Request"
|
||||
"name": "Supplier-Wise Sales Analytics",
|
||||
"reference_doctype": "Stock Ledger Entry",
|
||||
"onboard": 1
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Address And Contacts",
|
||||
"label": _("Supplier Addresses And Contacts"),
|
||||
"reference_doctype": "Address",
|
||||
"route_options": {
|
||||
"party_type": "Supplier"
|
||||
}
|
||||
"name": "Material Requests for which Supplier Quotations are not created",
|
||||
"reference_doctype": "Material Request"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -44,17 +44,6 @@ status_map = {
|
||||
["Closed", "eval:self.status=='Closed'"],
|
||||
["On Hold", "eval:self.status=='On Hold'"],
|
||||
],
|
||||
"Purchase Invoice": [
|
||||
["Draft", None],
|
||||
["Submitted", "eval:self.docstatus==1"],
|
||||
["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"],
|
||||
["Return", "eval:self.is_return==1 and self.docstatus==1"],
|
||||
["Debit Note Issued",
|
||||
"eval:self.outstanding_amount <= 0 and self.docstatus==1 and self.is_return==0 and get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"],
|
||||
["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
|
||||
["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
|
||||
["Cancelled", "eval:self.docstatus==2"],
|
||||
],
|
||||
"Purchase Order": [
|
||||
["Draft", None],
|
||||
["To Receive and Bill", "eval:self.per_received < 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||
|
@ -34,7 +34,7 @@ class StockController(AccountsController):
|
||||
gl_entries = self.get_gl_entries(warehouse_account)
|
||||
make_gl_entries(gl_entries, from_repost=from_repost)
|
||||
|
||||
if repost_future_gle:
|
||||
if (repost_future_gle or self.flags.repost_future_gle):
|
||||
items, warehouses = self.get_items_and_warehouses()
|
||||
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items,
|
||||
warehouse_account, company=self.company)
|
||||
@ -238,6 +238,10 @@ class StockController(AccountsController):
|
||||
for d in self.items:
|
||||
if not d.batch_no: continue
|
||||
|
||||
serial_nos = [d.name for d in frappe.get_all("Serial No", {'batch_no': d.batch_no})]
|
||||
if serial_nos:
|
||||
frappe.db.set_value("Serial No", { 'name': ['in', serial_nos] }, "batch_no", None)
|
||||
|
||||
d.batch_no = None
|
||||
d.db_set("batch_no", None)
|
||||
|
||||
|
@ -11,5 +11,12 @@ frappe.ui.form.on('Student Admission', {
|
||||
|
||||
academic_year: function(frm) {
|
||||
frm.trigger("program");
|
||||
},
|
||||
|
||||
admission_end_date: function(frm) {
|
||||
if(frm.doc.admission_end_date && frm.doc.admission_end_date <= frm.doc.admission_start_date){
|
||||
frm.set_value("admission_end_date", "");
|
||||
frappe.throw(__("Admission End Date should be greater than Admission Start Date."));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -39,19 +39,21 @@ class AdditionalSalary(Document):
|
||||
return amount_per_day * no_of_days
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_additional_salary_component(employee, start_date, end_date):
|
||||
def get_additional_salary_component(employee, start_date, end_date, component_type):
|
||||
additional_components = frappe.db.sql("""
|
||||
select salary_component, sum(amount) as amount, overwrite_salary_structure_amount, deduct_full_tax_on_selected_payroll_date
|
||||
from `tabAdditional Salary`
|
||||
where employee=%(employee)s
|
||||
and docstatus = 1
|
||||
and payroll_date between %(from_date)s and %(to_date)s
|
||||
and type = %(component_type)s
|
||||
group by salary_component, overwrite_salary_structure_amount
|
||||
order by salary_component, overwrite_salary_structure_amount
|
||||
""", {
|
||||
'employee': employee,
|
||||
'from_date': start_date,
|
||||
'to_date': end_date
|
||||
'to_date': end_date,
|
||||
'component_type': "Earning" if component_type == "earnings" else "Deduction"
|
||||
}, as_dict=1)
|
||||
|
||||
additional_components_list = []
|
||||
|
@ -1,720 +1,215 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "HR-TAX-PRF-.YYYY.-.#####",
|
||||
"beta": 0,
|
||||
"creation": "2018-04-13 17:24:11.456132",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "HR-TAX-PRF-.YYYY.-.#####",
|
||||
"creation": "2018-04-13 17:24:11.456132",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"employee",
|
||||
"employee_name",
|
||||
"department",
|
||||
"column_break_2",
|
||||
"submission_date",
|
||||
"payroll_period",
|
||||
"company",
|
||||
"section_break_5",
|
||||
"tax_exemption_proofs",
|
||||
"section_break_10",
|
||||
"total_actual_amount",
|
||||
"column_break_12",
|
||||
"exemption_amount",
|
||||
"other_incomes_section",
|
||||
"income_from_other_sources",
|
||||
"attachment_section",
|
||||
"attachments",
|
||||
"amended_from"
|
||||
],
|
||||
"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": "employee",
|
||||
"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": "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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Employee",
|
||||
"options": "Employee",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "employee.employee_name",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "employee_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": "Employee Name",
|
||||
"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
|
||||
},
|
||||
"fetch_from": "employee.employee_name",
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Employee Name",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "employee.department",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "department",
|
||||
"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": "Department",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Department",
|
||||
"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
|
||||
},
|
||||
"fetch_from": "employee.department",
|
||||
"fieldname": "department",
|
||||
"fieldtype": "Link",
|
||||
"label": "Department",
|
||||
"options": "Department",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"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_2",
|
||||
"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_2",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Today",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "submission_date",
|
||||
"fieldtype": "Date",
|
||||
"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": "Submission 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
|
||||
},
|
||||
"default": "Today",
|
||||
"fieldname": "submission_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Submission Date",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "payroll_period",
|
||||
"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": "Payroll Period",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Payroll Period",
|
||||
"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": "payroll_period",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Payroll Period",
|
||||
"options": "Payroll Period",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "employee.company",
|
||||
"fetch_if_empty": 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": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fetch_from": "employee.company",
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"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_5",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "tax_exemption_proofs",
|
||||
"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": "Tax Exemption Proofs",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee Tax Exemption Proof Submission Detail",
|
||||
"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": "tax_exemption_proofs",
|
||||
"fieldtype": "Table",
|
||||
"label": "Tax Exemption Proofs",
|
||||
"options": "Employee Tax Exemption Proof Submission Detail"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_10",
|
||||
"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_10",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_actual_amount",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Total Actual Amount",
|
||||
"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": "total_actual_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Actual Amount",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"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_12",
|
||||
"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_12",
|
||||
"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,
|
||||
"fieldname": "exemption_amount",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Total Exemption Amount",
|
||||
"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": "exemption_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Exemption Amount",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "other_incomes_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": "Other Incomes",
|
||||
"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": "other_incomes_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Other Incomes"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "income_from_other_sources",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Income From Other Sources",
|
||||
"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": "income_from_other_sources",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Income From Other Sources"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "attachment_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": "",
|
||||
"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": "attachment_section",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "attachments",
|
||||
"fieldtype": "Attach",
|
||||
"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": "Attachments",
|
||||
"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": "attachments",
|
||||
"fieldtype": "Attach",
|
||||
"label": "Attachments"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 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": "Employee Tax Exemption Proof Submission",
|
||||
"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": "Employee Tax Exemption Proof Submission",
|
||||
"print_hide": 1,
|
||||
"read_only": 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": "2019-05-13 12:17:18.045171",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Tax Exemption Proof Submission",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-03-02 19:02:15.398486",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Tax Exemption Proof Submission",
|
||||
"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": "HR 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": "HR 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": "HR User",
|
||||
"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": "HR User",
|
||||
"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": "Employee",
|
||||
"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": "Employee",
|
||||
"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": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -299,9 +299,11 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
def calculate_net_pay(self):
|
||||
if self.salary_structure:
|
||||
self.calculate_component_amounts()
|
||||
|
||||
self.calculate_component_amounts("earnings")
|
||||
self.gross_pay = self.get_component_totals("earnings")
|
||||
|
||||
if self.salary_structure:
|
||||
self.calculate_component_amounts("deductions")
|
||||
self.total_deduction = self.get_component_totals("deductions")
|
||||
|
||||
self.set_loan_repayment()
|
||||
@ -309,25 +311,27 @@ class SalarySlip(TransactionBase):
|
||||
self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))
|
||||
self.rounded_total = rounded(self.net_pay)
|
||||
|
||||
def calculate_component_amounts(self):
|
||||
def calculate_component_amounts(self, component_type):
|
||||
if not getattr(self, '_salary_structure_doc', None):
|
||||
self._salary_structure_doc = frappe.get_doc('Salary Structure', self.salary_structure)
|
||||
|
||||
payroll_period = get_payroll_period(self.start_date, self.end_date, self.company)
|
||||
|
||||
self.add_structure_components()
|
||||
self.add_employee_benefits(payroll_period)
|
||||
self.add_additional_salary_components()
|
||||
self.add_tax_components(payroll_period)
|
||||
self.set_component_amounts_based_on_payment_days()
|
||||
self.add_structure_components(component_type)
|
||||
self.add_additional_salary_components(component_type)
|
||||
if component_type == "earnings":
|
||||
self.add_employee_benefits(payroll_period)
|
||||
else:
|
||||
self.add_tax_components(payroll_period)
|
||||
|
||||
def add_structure_components(self):
|
||||
self.set_component_amounts_based_on_payment_days(component_type)
|
||||
|
||||
def add_structure_components(self, component_type):
|
||||
data = self.get_data_for_eval()
|
||||
for key in ('earnings', 'deductions'):
|
||||
for struct_row in self._salary_structure_doc.get(key):
|
||||
amount = self.eval_condition_and_formula(struct_row, data)
|
||||
if amount and struct_row.statistical_component == 0:
|
||||
self.update_component_row(struct_row, amount, key)
|
||||
for struct_row in self._salary_structure_doc.get(component_type):
|
||||
amount = self.eval_condition_and_formula(struct_row, data)
|
||||
if amount and struct_row.statistical_component == 0:
|
||||
self.update_component_row(struct_row, amount, component_type)
|
||||
|
||||
def get_data_for_eval(self):
|
||||
'''Returns data for evaluating formula'''
|
||||
@ -400,14 +404,15 @@ class SalarySlip(TransactionBase):
|
||||
amount = last_benefit.amount
|
||||
self.update_component_row(frappe._dict(last_benefit.struct_row), amount, "earnings")
|
||||
|
||||
def add_additional_salary_components(self):
|
||||
additional_components = get_additional_salary_component(self.employee, self.start_date, self.end_date)
|
||||
def add_additional_salary_components(self, component_type):
|
||||
additional_components = get_additional_salary_component(self.employee,
|
||||
self.start_date, self.end_date, component_type)
|
||||
if additional_components:
|
||||
for additional_component in additional_components:
|
||||
amount = additional_component.amount
|
||||
overwrite = additional_component.overwrite
|
||||
key = "earnings" if additional_component.type == "Earning" else "deductions"
|
||||
self.update_component_row(frappe._dict(additional_component.struct_row), amount, key, overwrite=overwrite)
|
||||
self.update_component_row(frappe._dict(additional_component.struct_row), amount,
|
||||
component_type, overwrite=overwrite)
|
||||
|
||||
def add_tax_components(self, payroll_period):
|
||||
# Calculate variable_based_on_taxable_salary after all components updated in salary slip
|
||||
@ -736,7 +741,7 @@ class SalarySlip(TransactionBase):
|
||||
total += d.amount
|
||||
return total
|
||||
|
||||
def set_component_amounts_based_on_payment_days(self):
|
||||
def set_component_amounts_based_on_payment_days(self, component_type):
|
||||
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
|
||||
["date_of_joining", "relieving_date"])
|
||||
|
||||
@ -746,9 +751,8 @@ class SalarySlip(TransactionBase):
|
||||
if not joining_date:
|
||||
frappe.throw(_("Please set the Date Of Joining for employee {0}").format(frappe.bold(self.employee_name)))
|
||||
|
||||
for component_type in ("earnings", "deductions"):
|
||||
for d in self.get(component_type):
|
||||
d.amount = self.get_amount_based_on_payment_days(d, joining_date, relieving_date)[0]
|
||||
for d in self.get(component_type):
|
||||
d.amount = self.get_amount_based_on_payment_days(d, joining_date, relieving_date)[0]
|
||||
|
||||
def set_loan_repayment(self):
|
||||
self.set('loans', [])
|
||||
|
@ -25,7 +25,6 @@ class TestSalaryStructure(unittest.TestCase):
|
||||
make_employee("test_employee@salary.com")
|
||||
make_employee("test_employee_2@salary.com")
|
||||
|
||||
|
||||
def make_holiday_list(self):
|
||||
if not frappe.db.get_value("Holiday List", "Salary Structure Test Holiday List"):
|
||||
holiday_list = frappe.get_doc({
|
||||
@ -38,6 +37,29 @@ class TestSalaryStructure(unittest.TestCase):
|
||||
holiday_list.get_weekly_off_dates()
|
||||
holiday_list.save()
|
||||
|
||||
def test_salary_structure_deduction_based_on_gross_pay(self):
|
||||
|
||||
emp = make_employee("test_employee_3@salary.com")
|
||||
|
||||
sal_struct = make_salary_structure("Salary Structure 2", "Monthly", dont_submit = True)
|
||||
|
||||
sal_struct.earnings = [sal_struct.earnings[0]]
|
||||
sal_struct.earnings[0].amount_based_on_formula = 1
|
||||
sal_struct.earnings[0].formula = "base"
|
||||
|
||||
sal_struct.deductions = [sal_struct.deductions[0]]
|
||||
|
||||
sal_struct.deductions[0].amount_based_on_formula = 1
|
||||
sal_struct.deductions[0].condition = "gross_pay > 100"
|
||||
sal_struct.deductions[0].formula = "gross_pay * 0.2"
|
||||
|
||||
sal_struct.submit()
|
||||
|
||||
assignment = create_salary_structure_assignment(emp, "Salary Structure 2")
|
||||
ss = make_salary_slip(sal_struct.name, employee = emp)
|
||||
|
||||
self.assertEqual(assignment.base * 0.2, ss.deductions[0].amount)
|
||||
|
||||
def test_amount_totals(self):
|
||||
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0)
|
||||
sal_slip = frappe.get_value("Salary Slip", {"employee_name":"test_employee_2@salary.com"})
|
||||
|
@ -75,7 +75,7 @@ class ShiftType(Document):
|
||||
for date in dates:
|
||||
shift_details = get_employee_shift(employee, date, True)
|
||||
if shift_details and shift_details.shift_type.name == self.name:
|
||||
mark_attendance(employee, date, self.name, 'Absent')
|
||||
mark_attendance(employee, date, 'Absent', self.name)
|
||||
|
||||
def get_assigned_employee(self, from_date=None, consider_default_shift=False):
|
||||
filters = {'date':('>=', from_date), 'shift_type': self.name, 'docstatus': '1'}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "ACC-LOAP-.YYYY.-.#####",
|
||||
"creation": "2019-08-29 17:46:49.201740",
|
||||
"doctype": "DocType",
|
||||
@ -122,7 +123,6 @@
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.is_term_loan == 1",
|
||||
"fetch_from": "loan_type.repayment_method",
|
||||
"fetch_if_empty": 1,
|
||||
"fieldname": "repayment_method",
|
||||
"fieldtype": "Select",
|
||||
@ -213,7 +213,8 @@
|
||||
}
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"modified": "2019-10-24 10:32:03.740558",
|
||||
"links": [],
|
||||
"modified": "2020-03-01 10:21:44.413353",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Loan Management",
|
||||
"name": "Loan Application",
|
||||
|
@ -55,7 +55,10 @@ def check_for_ltv_shortfall(process_loan_security_shortfall=None):
|
||||
"valid_upto": (">=", update_time)
|
||||
}, as_list=1))
|
||||
|
||||
loans = frappe.db.sql(""" SELECT l.name, l.loan_amount, l.total_principal_paid, lp.loan_security, lp.haircut, lp.qty
|
||||
ltv_ratio_map = frappe._dict(frappe.get_all("Loan Security Type",
|
||||
fields=["name", "loan_to_value_ratio"], as_list=1))
|
||||
|
||||
loans = frappe.db.sql(""" SELECT l.name, l.loan_amount, l.total_principal_paid, lp.loan_security, lp.haircut, lp.qty, lp.loan_security_type
|
||||
FROM `tabLoan` l, `tabPledge` lp , `tabLoan Security Pledge`p WHERE lp.parent = p.name and p.loan = l.name and l.docstatus = 1
|
||||
and l.is_secured_loan and l.status = 'Disbursed' and p.status in ('Pledged', 'Partially Unpledged')""", as_dict=1)
|
||||
|
||||
@ -68,11 +71,12 @@ def check_for_ltv_shortfall(process_loan_security_shortfall=None):
|
||||
})
|
||||
|
||||
current_loan_security_amount = loan_security_price_map.get(loan.loan_security, 0) * loan.qty
|
||||
ltv_ratio = ltv_ratio_map.get(loan.loan_security_type)
|
||||
|
||||
loan_security_map[loan.name]['security_value'] += current_loan_security_amount - (current_loan_security_amount * loan.haircut/100)
|
||||
|
||||
for loan, value in iteritems(loan_security_map):
|
||||
if value["security_value"] < value["loan_amount"]:
|
||||
if (value["security_value"]/value["loan_amount"]) < ltv_ratio:
|
||||
create_loan_security_shortfall(loan, value, process_loan_security_shortfall)
|
||||
|
||||
def create_loan_security_shortfall(loan, value, process_loan_security_shortfall):
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "field:loan_security_type",
|
||||
"creation": "2019-08-29 18:46:07.322056",
|
||||
"doctype": "DocType",
|
||||
@ -8,7 +9,9 @@
|
||||
"loan_security_type",
|
||||
"unit_of_measure",
|
||||
"haircut",
|
||||
"disabled"
|
||||
"disabled",
|
||||
"column_break_5",
|
||||
"loan_to_value_ratio"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@ -33,9 +36,19 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Unit Of Measure",
|
||||
"options": "UOM"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_5",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "loan_to_value_ratio",
|
||||
"fieldtype": "Percent",
|
||||
"label": "Loan To Value Ratio"
|
||||
}
|
||||
],
|
||||
"modified": "2019-10-10 03:05:37.912866",
|
||||
"links": [],
|
||||
"modified": "2020-02-28 12:43:20.364447",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Loan Management",
|
||||
"name": "Loan Security Type",
|
||||
|
@ -1,189 +1,76 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-05-23 16:55:51",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"creation": "2013-05-23 16:55:51",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"item_code",
|
||||
"qty",
|
||||
"description",
|
||||
"rate",
|
||||
"uom"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"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",
|
||||
"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": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"in_global_search": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Item",
|
||||
"oldfieldname": "item_code",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"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": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Qty",
|
||||
"oldfieldname": "qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"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": 0,
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Float",
|
||||
"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": "Rate",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"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": "rate",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 1,
|
||||
"label": "Rate",
|
||||
"oldfieldname": "rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"in_list_view": 1,
|
||||
"label": "UOM",
|
||||
"oldfieldname": "uom",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "UOM",
|
||||
"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:24:05.633546",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Product Bundle 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,
|
||||
"links": [],
|
||||
"modified": "2020-02-28 14:06:05.725655",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Product Bundle Item",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -108,8 +108,8 @@ def delete_lead_addresses(company_name):
|
||||
def delete_communications(doctype, company_name, company_fieldname):
|
||||
reference_docs = frappe.get_all(doctype, filters={company_fieldname:company_name})
|
||||
reference_doc_names = [r.name for r in reference_docs]
|
||||
|
||||
|
||||
communications = frappe.get_all("Communication", filters={"reference_doctype":doctype,"reference_name":["in", reference_doc_names]})
|
||||
communication_names = [c.name for c in communications]
|
||||
|
||||
frappe.delete_doc("Communication", communication_names)
|
||||
frappe.delete_doc("Communication", communication_names, ignore_permissions=True)
|
||||
|
@ -19,6 +19,11 @@ frappe.ui.form.on('Sales Person', {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
frm.make_methods = {
|
||||
'Sales Order': () => frappe.new_doc("Sales Order")
|
||||
.then(() => frm.add_child("sales_team", {"sales_person": frm.doc.name}))
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -981,6 +981,7 @@ def _msgprint(msg, verbose):
|
||||
def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0):
|
||||
"""returns last purchase details in stock uom"""
|
||||
# get last purchase order item details
|
||||
|
||||
last_purchase_order = frappe.db.sql("""\
|
||||
select po.name, po.transaction_date, po.conversion_rate,
|
||||
po_item.conversion_factor, po_item.base_price_list_rate,
|
||||
@ -991,6 +992,7 @@ def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0):
|
||||
order by po.transaction_date desc, po.name desc
|
||||
limit 1""", (item_code, cstr(doc_name)), as_dict=1)
|
||||
|
||||
|
||||
# get last purchase receipt item details
|
||||
last_purchase_receipt = frappe.db.sql("""\
|
||||
select pr.name, pr.posting_date, pr.posting_time, pr.conversion_rate,
|
||||
@ -1002,19 +1004,20 @@ def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0):
|
||||
order by pr.posting_date desc, pr.posting_time desc, pr.name desc
|
||||
limit 1""", (item_code, cstr(doc_name)), as_dict=1)
|
||||
|
||||
|
||||
|
||||
purchase_order_date = getdate(last_purchase_order and last_purchase_order[0].transaction_date
|
||||
or "1900-01-01")
|
||||
purchase_receipt_date = getdate(last_purchase_receipt and
|
||||
last_purchase_receipt[0].posting_date or "1900-01-01")
|
||||
|
||||
if (purchase_order_date > purchase_receipt_date) or \
|
||||
(last_purchase_order and not last_purchase_receipt):
|
||||
if last_purchase_order and (purchase_order_date >= purchase_receipt_date or not last_purchase_receipt):
|
||||
# use purchase order
|
||||
|
||||
last_purchase = last_purchase_order[0]
|
||||
purchase_date = purchase_order_date
|
||||
|
||||
elif (purchase_receipt_date > purchase_order_date) or \
|
||||
(last_purchase_receipt and not last_purchase_order):
|
||||
elif last_purchase_receipt and (purchase_receipt_date > purchase_order_date or not last_purchase_order):
|
||||
# use purchase receipt
|
||||
last_purchase = last_purchase_receipt[0]
|
||||
purchase_date = purchase_receipt_date
|
||||
@ -1026,10 +1029,11 @@ def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0):
|
||||
out = frappe._dict({
|
||||
"base_price_list_rate": flt(last_purchase.base_price_list_rate) / conversion_factor,
|
||||
"base_rate": flt(last_purchase.base_rate) / conversion_factor,
|
||||
"base_net_rate": flt(last_purchase.net_rate) / conversion_factor,
|
||||
"base_net_rate": flt(last_purchase.base_net_rate) / conversion_factor,
|
||||
"discount_percentage": flt(last_purchase.discount_percentage),
|
||||
"purchase_date": purchase_date
|
||||
})
|
||||
|
||||
|
||||
conversion_rate = flt(conversion_rate) or 1.0
|
||||
out.update({
|
||||
|
@ -10,7 +10,6 @@
|
||||
"item_code",
|
||||
"uom",
|
||||
"packing_unit",
|
||||
"min_qty",
|
||||
"column_break_17",
|
||||
"item_name",
|
||||
"brand",
|
||||
@ -63,13 +62,6 @@
|
||||
"fieldtype": "Int",
|
||||
"label": "Packing Unit"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "min_qty",
|
||||
"fieldtype": "Int",
|
||||
"in_list_view": 1,
|
||||
"label": "Minimum Qty "
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_17",
|
||||
"fieldtype": "Column Break"
|
||||
@ -216,7 +208,7 @@
|
||||
"icon": "fa fa-flag",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2019-12-31 03:11:09.702250",
|
||||
"modified": "2020-02-28 14:21:25.580331",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Item Price",
|
||||
@ -251,6 +243,7 @@
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"title_field": "item_name",
|
||||
"track_changes": 1
|
||||
|
@ -4,7 +4,6 @@
|
||||
"item_code": "_Test Item",
|
||||
"price_list": "_Test Price List",
|
||||
"price_list_rate": 100,
|
||||
"min_qty": 2,
|
||||
"valid_from": "2017-04-18",
|
||||
"valid_upto": "2017-04-26"
|
||||
},
|
||||
@ -12,8 +11,7 @@
|
||||
"doctype": "Item Price",
|
||||
"item_code": "_Test Item",
|
||||
"price_list": "_Test Price List Rest of the World",
|
||||
"price_list_rate": 10,
|
||||
"min_qty": 5
|
||||
"price_list_rate": 10
|
||||
},
|
||||
{
|
||||
"doctype": "Item Price",
|
||||
@ -22,7 +20,6 @@
|
||||
"price_list_rate": 20,
|
||||
"valid_from": "2017-04-18",
|
||||
"valid_upto": "2017-04-26",
|
||||
"min_qty": 7,
|
||||
"customer": "_Test Customer",
|
||||
"uom": "_Test UOM"
|
||||
},
|
||||
@ -31,19 +28,15 @@
|
||||
"item_code": "_Test Item Home Desktop 100",
|
||||
"price_list": "_Test Price List",
|
||||
"price_list_rate": 1000,
|
||||
"min_qty" : 10,
|
||||
"valid_from": "2017-04-10",
|
||||
"valid_upto": "2017-04-17",
|
||||
"min_qty": 2
|
||||
"valid_upto": "2017-04-17"
|
||||
},
|
||||
{
|
||||
"doctype": "Item Price",
|
||||
"item_code": "_Test Item Home Desktop Manufactured",
|
||||
"price_list": "_Test Price List",
|
||||
"price_list_rate": 1000,
|
||||
"min_qty" : 10,
|
||||
"valid_from": "2017-04-10",
|
||||
"valid_upto": "2017-04-17",
|
||||
"min_qty": 2
|
||||
"valid_upto": "2017-04-17"
|
||||
}
|
||||
]
|
||||
|
@ -7,6 +7,7 @@ import frappe, erpnext
|
||||
import frappe.defaults
|
||||
from frappe.utils import cint, flt, cstr, today, random_string
|
||||
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice
|
||||
from erpnext.stock.doctype.item.test_item import create_item
|
||||
from erpnext import set_perpetual_inventory
|
||||
from erpnext.stock.doctype.serial_no.serial_no import SerialNoDuplicateError
|
||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
||||
@ -50,6 +51,28 @@ class TestPurchaseReceipt(unittest.TestCase):
|
||||
self.assertEqual(current_bin_stock_value, existing_bin_stock_value + 250)
|
||||
|
||||
self.assertFalse(get_gl_entries("Purchase Receipt", pr.name))
|
||||
|
||||
def test_batched_serial_no_purchase(self):
|
||||
item = frappe.get_doc("Item", { 'item_name': 'Batched Serialized Item' })
|
||||
if not item:
|
||||
item = create_item("Batched Serialized Item")
|
||||
item.has_batch_no = 1
|
||||
item.create_new_batch = 1
|
||||
item.has_serial_no = 1
|
||||
item.batch_number_series = "BS-BATCH-.##"
|
||||
item.serial_no_series = "BS-.####"
|
||||
item.save()
|
||||
|
||||
pr = make_purchase_receipt(item_code=item.name, qty=5, rate=500)
|
||||
|
||||
self.assertTrue(frappe.db.get_value('Batch', {'item': item.name, 'reference_name': pr.name}))
|
||||
|
||||
pr.load_from_db()
|
||||
batch_no = pr.items[0].batch_no
|
||||
pr.cancel()
|
||||
|
||||
self.assertFalse(frappe.db.get_value('Batch', {'item': item.name, 'reference_name': pr.name}))
|
||||
self.assertFalse(frappe.db.get_all('Serial No', {'batch_no': batch_no}))
|
||||
|
||||
def test_purchase_receipt_gl_entry(self):
|
||||
pr = make_purchase_receipt(company="_Test Company with perpetual inventory", warehouse = "Stores - TCP1", supplier_warehouse = "Work in Progress - TCP1", get_multiple_items = True, get_taxes_and_charges = True)
|
||||
|
@ -6,6 +6,7 @@
|
||||
"description": "Distinct unit of an Item",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"details",
|
||||
"column_break0",
|
||||
@ -104,10 +105,11 @@
|
||||
},
|
||||
{
|
||||
"fieldname": "batch_no",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Batch No",
|
||||
"options": "Batch",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@ -425,7 +427,7 @@
|
||||
],
|
||||
"icon": "fa fa-barcode",
|
||||
"idx": 1,
|
||||
"modified": "2019-08-07 17:28:32.243280",
|
||||
"modified": "2020-02-28 19:31:09.357323",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Serial No",
|
||||
|
@ -205,6 +205,7 @@ def process_serial_no(sle):
|
||||
|
||||
def validate_serial_no(sle, item_det):
|
||||
serial_nos = get_serial_nos(sle.serial_no) if sle.serial_no else []
|
||||
validate_material_transfer_entry(sle)
|
||||
|
||||
if item_det.has_serial_no==0:
|
||||
if serial_nos:
|
||||
@ -224,7 +225,9 @@ def validate_serial_no(sle, item_det):
|
||||
|
||||
for serial_no in serial_nos:
|
||||
if frappe.db.exists("Serial No", serial_no):
|
||||
sr = frappe.get_doc("Serial No", serial_no)
|
||||
sr = frappe.db.get_value("Serial No", serial_no, ["name", "item_code", "batch_no", "sales_order",
|
||||
"delivery_document_no", "delivery_document_type", "warehouse",
|
||||
"purchase_document_no", "company"], as_dict=1)
|
||||
|
||||
if sr.item_code!=sle.item_code:
|
||||
if not allow_serial_nos_with_different_item(serial_no, sle):
|
||||
@ -305,6 +308,19 @@ def validate_serial_no(sle, item_det):
|
||||
frappe.throw(_("Cannot cancel {0} {1} because Serial No {2} does not belong to the warehouse {3}")
|
||||
.format(sle.voucher_type, sle.voucher_no, serial_no, sle.warehouse))
|
||||
|
||||
def validate_material_transfer_entry(sle_doc):
|
||||
sle_doc.update({
|
||||
"skip_update_serial_no": False,
|
||||
"skip_serial_no_validaiton": False
|
||||
})
|
||||
|
||||
if (sle_doc.voucher_type == "Stock Entry" and sle_doc.is_cancelled == "No" and
|
||||
frappe.get_cached_value("Stock Entry", sle_doc.voucher_no, "purpose") == "Material Transfer"):
|
||||
if sle_doc.actual_qty < 0:
|
||||
sle_doc.skip_update_serial_no = True
|
||||
else:
|
||||
sle_doc.skip_serial_no_validaiton = True
|
||||
|
||||
def validate_so_serial_no(sr, sales_order,):
|
||||
if not sr.sales_order or sr.sales_order!= sales_order:
|
||||
frappe.throw(_("""Sales Order {0} has reservation for item {1}, you can
|
||||
@ -312,7 +328,8 @@ def validate_so_serial_no(sr, sales_order,):
|
||||
be delivered""").format(sales_order, sr.item_code, sr.name))
|
||||
|
||||
def has_duplicate_serial_no(sn, sle):
|
||||
if sn.warehouse and sle.voucher_type != 'Stock Reconciliation':
|
||||
if (sn.warehouse and not sle.skip_serial_no_validaiton
|
||||
and sle.voucher_type != 'Stock Reconciliation'):
|
||||
return True
|
||||
|
||||
if sn.company != sle.company:
|
||||
@ -337,7 +354,7 @@ def allow_serial_nos_with_different_item(sle_serial_no, sle):
|
||||
"""
|
||||
allow_serial_nos = False
|
||||
if sle.voucher_type=="Stock Entry" and cint(sle.actual_qty) > 0:
|
||||
stock_entry = frappe.get_doc("Stock Entry", sle.voucher_no)
|
||||
stock_entry = frappe.get_cached_doc("Stock Entry", sle.voucher_no)
|
||||
if stock_entry.purpose in ("Repack", "Manufacture"):
|
||||
for d in stock_entry.get("items"):
|
||||
if d.serial_no and (d.s_warehouse if sle.is_cancelled=="No" else d.t_warehouse):
|
||||
@ -348,6 +365,7 @@ def allow_serial_nos_with_different_item(sle_serial_no, sle):
|
||||
return allow_serial_nos
|
||||
|
||||
def update_serial_nos(sle, item_det):
|
||||
if sle.skip_update_serial_no: return
|
||||
if sle.is_cancelled == "No" and not sle.serial_no and cint(sle.actual_qty) > 0 \
|
||||
and item_det.has_serial_no == 1 and item_det.serial_no_series:
|
||||
serial_nos = get_auto_serial_nos(item_det.serial_no_series, sle.actual_qty)
|
||||
@ -369,22 +387,16 @@ def auto_make_serial_nos(args):
|
||||
voucher_type = args.get('voucher_type')
|
||||
item_code = args.get('item_code')
|
||||
for serial_no in serial_nos:
|
||||
is_new = False
|
||||
if frappe.db.exists("Serial No", serial_no):
|
||||
sr = frappe.get_doc("Serial No", serial_no)
|
||||
sr.via_stock_ledger = True
|
||||
sr.item_code = item_code
|
||||
sr.warehouse = args.get('warehouse') if args.get('actual_qty', 0) > 0 else None
|
||||
sr.batch_no = args.get('batch_no')
|
||||
sr.location = args.get('location')
|
||||
sr.company = args.get('company')
|
||||
sr.supplier = args.get('supplier')
|
||||
if sr.sales_order and voucher_type == "Stock Entry" \
|
||||
and not args.get('actual_qty', 0) > 0:
|
||||
sr.sales_order = None
|
||||
sr.update_serial_no_reference()
|
||||
sr.save(ignore_permissions=True)
|
||||
sr = frappe.get_cached_doc("Serial No", serial_no)
|
||||
elif args.get('actual_qty', 0) > 0:
|
||||
created_numbers.append(make_serial_no(serial_no, args))
|
||||
sr = frappe.new_doc("Serial No")
|
||||
is_new = True
|
||||
|
||||
sr = update_args_for_serial_no(sr, serial_no, args, is_new=is_new)
|
||||
if is_new:
|
||||
created_numbers.append(sr.name)
|
||||
|
||||
form_links = list(map(lambda d: frappe.utils.get_link_to_form('Serial No', d), created_numbers))
|
||||
|
||||
@ -419,20 +431,34 @@ def get_serial_nos(serial_no):
|
||||
return [s.strip() for s in cstr(serial_no).strip().upper().replace(',', '\n').split('\n')
|
||||
if s.strip()]
|
||||
|
||||
def make_serial_no(serial_no, args):
|
||||
sr = frappe.new_doc("Serial No")
|
||||
sr.serial_no = serial_no
|
||||
sr.item_code = args.get('item_code')
|
||||
sr.company = args.get('company')
|
||||
sr.batch_no = args.get('batch_no')
|
||||
sr.via_stock_ledger = args.get('via_stock_ledger') or True
|
||||
sr.warehouse = args.get('warehouse')
|
||||
def update_args_for_serial_no(serial_no_doc, serial_no, args, is_new=False):
|
||||
serial_no_doc.update({
|
||||
"item_code": args.get("item_code"),
|
||||
"company": args.get("company"),
|
||||
"batch_no": args.get("batch_no"),
|
||||
"via_stock_ledger": args.get("via_stock_ledger") or True,
|
||||
"supplier": args.get("supplier"),
|
||||
"location": args.get("location"),
|
||||
"warehouse": (args.get("warehouse")
|
||||
if args.get("actual_qty", 0) > 0 else None)
|
||||
})
|
||||
|
||||
sr.validate_item()
|
||||
sr.update_serial_no_reference(serial_no)
|
||||
sr.db_insert()
|
||||
if is_new:
|
||||
serial_no_doc.serial_no = serial_no
|
||||
|
||||
return sr.name
|
||||
if (serial_no_doc.sales_order and args.get("voucher_type") == "Stock Entry"
|
||||
and not args.get("actual_qty", 0) > 0):
|
||||
serial_no_doc.sales_order = None
|
||||
|
||||
serial_no_doc.validate_item()
|
||||
serial_no_doc.update_serial_no_reference(serial_no)
|
||||
|
||||
if is_new:
|
||||
serial_no_doc.db_insert()
|
||||
else:
|
||||
serial_no_doc.db_update()
|
||||
|
||||
return serial_no_doc
|
||||
|
||||
def update_serial_nos_after_submit(controller, parentfield):
|
||||
stock_ledger_entries = frappe.db.sql("""select voucher_detail_no, serial_no, actual_qty, warehouse
|
||||
|
@ -240,6 +240,7 @@
|
||||
"options": "Company",
|
||||
"print_width": "150px",
|
||||
"read_only": 1,
|
||||
"search_index": 1,
|
||||
"width": "150px"
|
||||
},
|
||||
{
|
||||
@ -274,7 +275,7 @@
|
||||
"icon": "fa fa-list",
|
||||
"idx": 1,
|
||||
"in_create": 1,
|
||||
"modified": "2019-11-27 12:17:31.522675",
|
||||
"modified": "2020-02-25 22:53:33.504681",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Stock Ledger Entry",
|
||||
|
@ -136,7 +136,7 @@ def get_bin(item_code, warehouse):
|
||||
bin_obj.flags.ignore_permissions = 1
|
||||
bin_obj.insert()
|
||||
else:
|
||||
bin_obj = frappe.get_doc('Bin', bin)
|
||||
bin_obj = frappe.get_cached_doc('Bin', bin)
|
||||
bin_obj.flags.ignore_permissions = True
|
||||
return bin_obj
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -27,7 +27,6 @@ apps/erpnext/erpnext/stock/doctype/material_request/material_request.py,{0} {1}
|
||||
apps/erpnext/erpnext/stock/doctype/delivery_note/delivery_note.py,Packing Slip(s) cancelled,Packing Slip(s) canceled
|
||||
DocType: Payment Entry,Cheque/Reference No,Check/Reference No
|
||||
apps/erpnext/erpnext/assets/doctype/asset/asset.py,"Asset cannot be cancelled, as it is already {0}","Asset cannot be canceled, as it is already {0}"
|
||||
DocType: Bank Reconciliation,Select account head of the bank where cheque was deposited.,Select account head of the bank where check was deposited.
|
||||
DocType: Cheque Print Template,Cheque Print Template,Check Print Template
|
||||
apps/erpnext/erpnext/controllers/selling_controller.py,{0} {1} is cancelled or closed,{0} {1} is canceled or closed
|
||||
apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py,Quotation {0} is cancelled,Quotation {0} is canceled
|
||||
|
|
File diff suppressed because it is too large
Load Diff
@ -544,7 +544,7 @@ DocType: Journal Entry,Excise Entry,Entrada Impuestos Especiales
|
||||
DocType: Attendance,Leave Type,Tipo de Vacaciones
|
||||
DocType: Account,Round Off,Redondear
|
||||
DocType: BOM Item,Scrap %,Chatarra %
|
||||
,Requested,Requerido
|
||||
DocType: Loan Security Pledge,Requested,Requerido
|
||||
DocType: Account,Stock Received But Not Billed,Inventario Recibido pero no facturados
|
||||
DocType: Monthly Distribution,Distribution Name,Nombre del Distribución
|
||||
apps/erpnext/erpnext/buying/report/procurement_tracker/procurement_tracker.py,Material Request No,Nº de Solicitud de Material
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -337,7 +337,7 @@ apps/erpnext/erpnext/config/manufacturing.py,Time Sheet for manufacturing.,זמ
|
||||
apps/erpnext/erpnext/accounts/report/trial_balance/trial_balance.py,Opening (Cr),פתיחה (Cr)
|
||||
DocType: Tally Migration,Round Off Account,לעגל את החשבון
|
||||
DocType: Payment Reconciliation Payment,Reference Row,הפניה Row
|
||||
DocType: Employee,Job Applicant,עבודת מבקש
|
||||
DocType: Appointment Letter,Job Applicant,עבודת מבקש
|
||||
apps/erpnext/erpnext/setup/setup_wizard/data/industry_type.py,Entertainment & Leisure,בידור ופנאי
|
||||
apps/erpnext/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py,Opening,פתיחה
|
||||
DocType: Bank Account,Party Type,סוג המפלגה
|
||||
@ -662,7 +662,7 @@ DocType: Sales Invoice Item,References,אזכור
|
||||
DocType: Item,Synced With Hub,סונכרן עם רכזת
|
||||
apps/erpnext/erpnext/manufacturing/doctype/work_order/work_order.py,Sales Order {0} is not valid,להזמין מכירות {0} אינו חוקי
|
||||
apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py,Warehouse not found in the system,מחסן לא נמצא במערכת
|
||||
apps/erpnext/erpnext/accounts/report/purchase_register/purchase_register.py,Total Tax,"מס סה""כ"
|
||||
apps/erpnext/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py,Total Tax,"מס סה""כ"
|
||||
apps/erpnext/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py,{0} payment entries can not be filtered by {1},לא יכולים להיות מסוננים {0} ערכי תשלום על ידי {1}
|
||||
DocType: Period Closing Voucher,Closing Account Head,סגירת חשבון ראש
|
||||
apps/erpnext/erpnext/setup/setup_wizard/operations/install_fixtures.py,Stock Options,אופציות
|
||||
@ -1044,7 +1044,7 @@ apps/erpnext/erpnext/controllers/buying_controller.py,Specified BOM {0} does not
|
||||
apps/erpnext/erpnext/manufacturing/doctype/work_order/work_order.js,{0} items produced,{0} פריטים המיוצרים
|
||||
DocType: Communication Medium,Communication Medium,תקשורת בינונית
|
||||
DocType: Department Approver,Approver,מאשר
|
||||
DocType: Job Applicant,Applicant Name,שם מבקש
|
||||
DocType: Appointment Letter,Applicant Name,שם מבקש
|
||||
DocType: Stock Entry,Including items for sub assemblies,כולל פריטים למכלולים תת
|
||||
DocType: Employee,Permanent Address Is,כתובת קבע
|
||||
DocType: Share Transfer,Issue,נושא
|
||||
@ -1774,7 +1774,7 @@ DocType: Item,Is Sales Item,האם פריט מכירות
|
||||
,Purchase Order Items To Be Received,פריטים הזמנת רכש שיתקבלו
|
||||
apps/erpnext/erpnext/accounts/report/trial_balance/trial_balance.py,Closing (Cr),סגירה (Cr)
|
||||
DocType: Account,Cash,מזומנים
|
||||
DocType: Certification Application,Payment Details,פרטי תשלום
|
||||
DocType: Loan Repayment,Payment Details,פרטי תשלום
|
||||
DocType: Fee Schedule,In Process,בתהליך
|
||||
apps/erpnext/erpnext/setup/doctype/company/company.js,Wrong Password,סיסמא שגויה
|
||||
apps/erpnext/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py,Please click on 'Generate Schedule' to fetch Serial No added for Item {0},אנא לחץ על 'צור לוח זמנים' כדי להביא מספר סידורי הוסיפה לפריט {0}
|
||||
@ -1882,7 +1882,7 @@ apps/erpnext/erpnext/controllers/buying_controller.py,From {0} | {1} {2},מ {0}
|
||||
DocType: Naming Series,Current Value,ערך נוכחי
|
||||
apps/erpnext/erpnext/public/js/account_tree_grid.js,Select Fiscal Year...,בחר שנת כספים ...
|
||||
apps/erpnext/erpnext/controllers/trends.py,Amt,AMT
|
||||
,Requested,ביקשתי
|
||||
DocType: Loan Security Pledge,Requested,ביקשתי
|
||||
DocType: BOM Update Tool,Current BOM,BOM הנוכחי
|
||||
DocType: Purchase Invoice,Advance Payments,תשלומים מראש
|
||||
DocType: Asset Maintenance,Manufacturing User,משתמש ייצור
|
||||
@ -1974,6 +1974,7 @@ DocType: Purchase Invoice,Select Supplier Address,כתובת ספק בחר
|
||||
DocType: SMS Center,SMS Center,SMS מרכז
|
||||
apps/erpnext/erpnext/accounts/report/cash_flow/cash_flow.py,Cash Flow from Investing,תזרים מזומנים מהשקעות
|
||||
DocType: Stock Entry Detail,Basic Amount,סכום בסיסי
|
||||
DocType: Loan Repayment,Amount Paid,הסכום ששולם
|
||||
apps/erpnext/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py,Investments,השקעות
|
||||
DocType: Serial No,Under Warranty,במסגרת אחריות
|
||||
DocType: Price List,Price List Name,שם מחיר המחירון
|
||||
@ -2475,7 +2476,6 @@ DocType: Job Applicant,Applicant for a Job,מועמד לעבודה
|
||||
apps/erpnext/erpnext/accounts/doctype/payment_entry/payment_entry.py,Reference No and Reference Date is mandatory for Bank transaction,אסמכתא ותאריך ההפניה הוא חובה עבור עסקת הבנק
|
||||
DocType: Cheque Print Template,Signatory Position,תפקיד החותם
|
||||
,Item-wise Sales Register,פריט חכם מכירות הרשמה
|
||||
DocType: Bank Reconciliation,Select account head of the bank where cheque was deposited.,ראש בחר חשבון של הבנק שבו הופקד שיק.
|
||||
DocType: Pricing Rule,Margin,Margin
|
||||
apps/erpnext/erpnext/manufacturing/doctype/bom/bom.js,Qty To Manufacture,כמות לייצור
|
||||
DocType: Bank Statement Transaction Settings Item,Transaction,עסקה
|
||||
@ -2658,7 +2658,7 @@ apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.js,Debit Accou
|
||||
apps/erpnext/erpnext/stock/doctype/serial_no/serial_no.py,Serial No {0} has already been received,מספר סידורי {0} כבר קיבל
|
||||
,To Produce,כדי לייצר
|
||||
DocType: Item Price,Multiple Item prices.,מחירי פריט מרובים.
|
||||
DocType: Job Card,Production,הפקה
|
||||
DocType: Plaid Settings,Production,הפקה
|
||||
DocType: Appointment Booking Settings,Holiday List,רשימת החג
|
||||
apps/erpnext/erpnext/accounts/doctype/account/account_tree.js,"Optional. Sets company's default currency, if not specified.","אופציונאלי. סטי ברירת מחדל המטבע של החברה, אם לא צוין."
|
||||
apps/erpnext/erpnext/public/js/setup_wizard.js,The name of the institute for which you are setting up this system.,שמו של המכון אשר אתה מגדיר מערכת זו.
|
||||
@ -3173,6 +3173,7 @@ DocType: Monthly Distribution,Name of the Monthly Distribution,שמו של הח
|
||||
,Item Shortage Report,דווח מחסור פריט
|
||||
apps/erpnext/erpnext/stock/doctype/serial_no/serial_no.py,Item {0} is not setup for Serial Nos. Check Item master,פריט {0} הוא לא התקנה למס סידורי. בדוק אדון פריט
|
||||
apps/erpnext/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.js,Print settings updated in respective print format,הגדרות הדפסה עודכנו מודפסות בהתאמה
|
||||
apps/erpnext/erpnext/loan_management/doctype/loan_type/loan_type.py,Account {0} does not belong to Company {1},חשבון {0} אינו שייך לחברת {1}
|
||||
apps/erpnext/erpnext/public/js/setup_wizard.js,The name of your company for which you are setting up this system.,שמה של החברה שלך שאתה מגדיר את המערכת הזאת.
|
||||
apps/erpnext/erpnext/education/doctype/student_applicant/student_applicant.js,Approve,לְאַשֵׁר
|
||||
apps/erpnext/erpnext/hr/doctype/holiday_list/holiday_list.py,The holiday on {0} is not between From Date and To Date,החג על {0} הוא לא בין מתאריך ו עד תאריך
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -251,7 +251,7 @@ DocType: Employee,Health Details,Detalhes sobre a Saúde
|
||||
DocType: Accounts Settings,"Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.","Registros contábeis congelados até a presente data, ninguém pode criar/modificar registros com exceção do perfil especificado abaixo."
|
||||
apps/erpnext/erpnext/hr/doctype/expense_claim/expense_claim.py,Total advance amount cannot be greater than total sanctioned amount,O montante do adiantamento total não pode ser maior do que o montante liberado total
|
||||
,Payment Period Based On Invoice Date,Prazo Médio de Pagamento Baseado na Emissão da Nota
|
||||
apps/erpnext/erpnext/accounts/report/purchase_register/purchase_register.py,Total Tax,Total de Impostos
|
||||
apps/erpnext/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py,Total Tax,Total de Impostos
|
||||
DocType: Delivery Note,Return Against Delivery Note,Devolução contra Guia de Remessa
|
||||
apps/erpnext/erpnext/accounts/utils.py,Payment Entries {0} are un-linked,Os Registos de Pagamento {0} não estão relacionados
|
||||
apps/erpnext/erpnext/stock/doctype/delivery_note/delivery_note_list.js,Cannot create a Delivery Trip from Draft documents.,Você não pode criar uma Viagem de Entrega para documentos em rascunho.
|
||||
@ -553,6 +553,7 @@ apps/erpnext/erpnext/controllers/selling_controller.py,Sales Order {0} is {1},Pe
|
||||
DocType: Patient,Married,Casado
|
||||
apps/erpnext/erpnext/setup/setup_wizard/data/industry_type.py,Executive Search,Executive Search
|
||||
,Itemwise Recommended Reorder Level,Níves de Reposição Recomendados por Item
|
||||
DocType: Loan Repayment,Amount Paid,Valor pago
|
||||
DocType: Guardian,Guardian Of ,Responsável por
|
||||
DocType: Bank Statement Transaction Entry,Receivable Account,Contas a Receber
|
||||
DocType: Job Offer,Printing Details,Imprimir detalhes
|
||||
@ -651,7 +652,7 @@ apps/erpnext/erpnext/manufacturing/doctype/production_plan/production_plan.js,"R
|
||||
DocType: Authorization Rule,Applicable To (User),Aplicável Para (Usuário)
|
||||
apps/erpnext/erpnext/controllers/trends.py,Total(Amt),Total (Quantia)
|
||||
apps/erpnext/erpnext/selling/doctype/installation_note/installation_note.py,Item {0} is not a serialized Item,Item {0} não é um item serializado
|
||||
apps/erpnext/erpnext/hr/doctype/loan/loan.js,Principal Amount,Valor Principal
|
||||
DocType: Repayment Schedule,Principal Amount,Valor Principal
|
||||
apps/erpnext/erpnext/config/projects.py,Timesheet for tasks.,Registros de Tempo para tarefas.
|
||||
apps/erpnext/erpnext/selling/doctype/installation_note/installation_note.py,Installation date cannot be before delivery date for Item {0},Data de instalação não pode ser anterior à data de entrega de item {0}
|
||||
apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py,{0} is mandatory for Item {1},{0} é obrigatório para o item {1}
|
||||
@ -771,7 +772,7 @@ apps/erpnext/erpnext/accounts/doctype/account/chart_of_accounts/verified/standar
|
||||
apps/erpnext/erpnext/healthcare/doctype/lab_test/lab_test.js,Send SMS,Envie SMS
|
||||
apps/erpnext/erpnext/education/doctype/student_admission/templates/student_admission.html,Apply Now,Aplique agora
|
||||
apps/erpnext/erpnext/config/buying.py,Request for quotation.,Solicitação de orçamento.
|
||||
DocType: Loan,Total Payment,Pagamento Total
|
||||
DocType: Repayment Schedule,Total Payment,Pagamento Total
|
||||
DocType: Work Order,Manufactured Qty,Qtde Fabricada
|
||||
DocType: Leave Application,Leave Approver Name,Nome do Aprovador de Licenças
|
||||
DocType: Employee Attendance Tool,Employees HTML,Colaboradores HTML
|
||||
@ -842,7 +843,6 @@ DocType: Clinical Procedure,Inpatient Record,Registro de Internação
|
||||
DocType: Fee Schedule Program,Student Batch,Série de Alunos
|
||||
apps/erpnext/erpnext/stock/doctype/material_request/material_request.js,Fetch exploded BOM (including sub-assemblies),Buscar LDM explodida (incluindo sub-conjuntos )
|
||||
DocType: Lead,Lead is an Organization,Cliente em Potencial é uma Empresa
|
||||
DocType: Loan Application,Required by Date,Necessário até a data
|
||||
DocType: Purchase Taxes and Charges,Reference Row #,Referência Linha #
|
||||
DocType: Payroll Entry,Employee Details,Detalhes do Funcionário
|
||||
apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py,Customer {0} does not belong to project {1},Cliente {0} não pertence ao projeto {1}
|
||||
@ -1650,7 +1650,7 @@ apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py,Total Debit
|
||||
apps/erpnext/erpnext/crm/report/prospects_engaged_but_not_converted/prospects_engaged_but_not_converted.py,Last Communication Date,Data do Último Contato
|
||||
DocType: Work Order,Manufacture against Material Request,Fabricação Vinculada a uma Requisição de Material
|
||||
DocType: Email Digest,Payables,Contas a Pagar
|
||||
DocType: Vehicle Log,Odometer,Odômetro
|
||||
apps/erpnext/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py,Odometer,Odômetro
|
||||
DocType: Employee Attendance Tool,Marked Attendance HTML,Presença marcante HTML
|
||||
apps/erpnext/erpnext/setup/setup_wizard/data/industry_type.py,Department Stores,Lojas de Departamento
|
||||
DocType: Issue,First Responded On,Primeira Resposta em
|
||||
@ -1761,7 +1761,7 @@ apps/erpnext/erpnext/selling/page/point_of_sale/point_of_sale.js,POS Profile is
|
||||
DocType: Manufacturing Settings,Capacity Planning,Planejamento de capacidade
|
||||
apps/erpnext/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.js,Please select {0},Por favor selecione {0}
|
||||
DocType: Employee Tax Exemption Declaration Category,Employee Tax Exemption Declaration Category,Categoria de Declaração de Isenção de Imposto do Colaborador
|
||||
DocType: Loan Application,Total Payable Amount,Total a Pagar
|
||||
DocType: Loan,Total Payable Amount,Total a Pagar
|
||||
apps/erpnext/erpnext/controllers/accounts_controller.py,Charge of type 'Actual' in row {0} cannot be included in Item Rate,Charge do tipo ' real ' na linha {0} não pode ser incluído no item Taxa
|
||||
DocType: Work Order,Work-in-Progress Warehouse,Armazén de Trabalho em Andamento
|
||||
apps/erpnext/erpnext/education/doctype/student/student.py,Date of Birth cannot be greater than today.,Data de nascimento não pode ser maior do que hoje.
|
||||
@ -2527,7 +2527,7 @@ DocType: Pick List,Parent Warehouse,Armazén Pai
|
||||
apps/erpnext/erpnext/portal/doctype/homepage/homepage.py,This is an example website auto-generated from ERPNext,Este é um exemplo website auto- gerada a partir ERPNext
|
||||
DocType: Chapter Member,Leave Reason,Motivo da Saída
|
||||
DocType: Item Group,Show this slideshow at the top of the page,Mostrar esta apresentação de slides no topo da página
|
||||
DocType: Loan Type,Maximum Loan Amount,Valor Máximo de Empréstimo
|
||||
DocType: Loan Application,Maximum Loan Amount,Valor Máximo de Empréstimo
|
||||
DocType: Serial No,Creation Time,Horário de Criação
|
||||
DocType: Employee Incentive,Employee Incentive,Incentivo ao Colaborador
|
||||
DocType: Leave Allocation,Total Leaves Allocated,Total de licenças alocadas
|
||||
@ -3006,11 +3006,10 @@ apps/erpnext/erpnext/controllers/accounts_controller.py,Due Date is mandatory,A
|
||||
DocType: Manufacturing Settings,Material Transferred for Manufacture,Material Transferido para Fabricação
|
||||
,Employee Information,Informações do Colaborador
|
||||
DocType: Purchase Invoice,Start date of current invoice's period,Data de início do período de fatura atual
|
||||
DocType: Bank Reconciliation,Select account head of the bank where cheque was deposited.,Selecione a conta bancária onde o valor foi depositado.
|
||||
DocType: Production Plan Item,Product Bundle Item,Item do Pacote de Produtos
|
||||
apps/erpnext/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js,Please enter Purchase Receipt first,Digite Recibo de compra primeiro
|
||||
DocType: Opportunity,Contact Info,Informações para Contato
|
||||
DocType: Employee,Job Applicant,Candidato à Vaga
|
||||
DocType: Appointment Letter,Job Applicant,Candidato à Vaga
|
||||
apps/erpnext/erpnext/setup/setup_wizard/data/industry_type.py,Newspaper Publishers,Editor de Newsletter
|
||||
DocType: Sales Order Item,Supplier delivers to Customer,O fornecedor entrega diretamente ao cliente
|
||||
apps/erpnext/erpnext/setup/setup_wizard/operations/install_fixtures.py,Extra Small,Muito Pequeno
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -302,6 +302,7 @@ apps/erpnext/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_re
|
||||
DocType: Shopping Cart Settings,Enable Shopping Cart,Omogući korpu
|
||||
DocType: Purchase Invoice Item,Is Fixed Asset,Artikal je osnovno sredstvo
|
||||
,POS,POS
|
||||
DocType: Loan Repayment,Amount Paid,Plaćeni iznos
|
||||
apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py,Timesheet {0} is already completed or cancelled,Potrošeno vrijeme {0} je već potvrđeno ili otkazano
|
||||
apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.py, (Half Day),(Pola dana)
|
||||
DocType: Shipping Rule,Net Weight,Neto težina
|
||||
@ -589,6 +590,7 @@ apps/erpnext/erpnext/stock/doctype/material_request/material_request_dashboard.p
|
||||
DocType: Warehouse,Warehouse Name,Naziv skladišta
|
||||
DocType: Authorization Rule,Customer / Item Name,Kupac / Naziv proizvoda
|
||||
DocType: Timesheet,Total Billed Amount,Ukupno fakturisano
|
||||
DocType: Student,Home Address,Kućna adresa
|
||||
apps/erpnext/erpnext/stock/report/stock_balance/stock_balance.py,In Value,Prijem vrije.
|
||||
DocType: Expense Claim,Employees Email Id,ID email Zaposlenih
|
||||
apps/erpnext/erpnext/healthcare/page/appointment_analytic/appointment_analytic.js,Tree Type,Tip stabla
|
||||
@ -789,7 +791,7 @@ DocType: Production Plan,For Warehouse,Za skladište
|
||||
apps/erpnext/erpnext/stock/report/item_prices/item_prices.py,Purchase Price List,Nabavni cjenovnik
|
||||
apps/erpnext/erpnext/accounts/report/accounts_payable/accounts_payable.js,Accounts Payable Summary,Pregled obaveze prema dobavljačima
|
||||
apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py,Delivery Notes {0} must be cancelled before cancelling this Sales Order,Otpremnice {0} moraju biti otkazane prije otkazivanja prodajnog naloga
|
||||
DocType: Loan,Total Payment,Ukupno plaćeno
|
||||
DocType: Repayment Schedule,Total Payment,Ukupno plaćeno
|
||||
DocType: POS Settings,POS Settings,POS podešavanja
|
||||
apps/erpnext/erpnext/accounts/report/gross_profit/gross_profit.py,Buying Amount,Iznos nabavke
|
||||
DocType: Purchase Invoice Item,Valuation Rate,Prosječna nab. cijena
|
||||
@ -916,7 +918,7 @@ DocType: Pick List,Material Transfer for Manufacture,Пренос robe za proizv
|
||||
apps/erpnext/erpnext/public/js/utils/customer_quick_entry.js,Primary Contact Details,Detalji o primarnom kontaktu
|
||||
apps/erpnext/erpnext/accounts/report/general_ledger/general_ledger.html,Ref,Vezni dokument
|
||||
DocType: Account,Accounts,Računi
|
||||
,Requested,Tražena
|
||||
DocType: Loan Security Pledge,Requested,Tražena
|
||||
apps/erpnext/erpnext/controllers/selling_controller.py,{0} {1} is cancelled or closed,{0} {1} je otkazan ili zatvoren
|
||||
DocType: Request for Quotation Item,Request for Quotation Item,Zahtjev za stavku sa ponude
|
||||
DocType: Homepage,Products,Proizvodi
|
||||
|
|
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
Loading…
Reference in New Issue
Block a user