fix: Merge branch hotfix into quotation-fix

This commit is contained in:
deepeshgarg007
2019-04-24 14:53:30 +05:30
72 changed files with 5068 additions and 1053 deletions

View File

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

View File

@@ -1,6 +1,6 @@
{
"country_code": "de",
"name": "Germany - Kontenplan SKR04",
"name": "SKR04 ohne Kontonummern",
"tree": {
"Bilanz - Aktiva": {
"Anlageverm\u00f6gen": {
@@ -1383,8 +1383,7 @@
"Sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge 1": {
"Diskontertr\u00e4ge": {},
"Diskontertr\u00e4ge aus verbundenen Unternehmen": {},
"Laufende Ertr\u00e4ge aus Anteilen an Kapitalgesellschaften 100% / 50% steuerfrei": {},
"Laufende Ertr\u00e4ge aus Anteilen an Kapitalgesellschaften 100% / 50% steuerfrei": {},
"Laufende Ertr\u00e4ge aus Anteilen an Kapitalgesellschaften 100% / 50% steuerfrei": {},
"Sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge 2": {},
"Sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge aus verbundenen Unternehmen": {},
"Sonstige Zinsertr\u00e4ge": {},
@@ -1703,4 +1702,4 @@
"root_type": "Asset"
}
}
}
}

View File

@@ -38,24 +38,24 @@
"Kas": {
"Kas Mata Uang Lain": {
"Kas USD": {
"account_number": "1112.0010",
"account_number": "1112.001",
"account_type": "Cash"
},
"account_number": "1112.000"
},
"Kas Rupiah": {
"Kas Besar": {
"account_number": "1111.0020",
"account_number": "1111.002",
"account_type": "Cash"
},
"Kas Kecil": {
"account_number": "1111.0010",
"account_number": "1111.001",
"account_type": "Cash"
},
"account_number": "1111.000",
"account_type": "Cash"
},
"account_number": "1110.0000"
"account_number": "1110.000"
},
"Pendapatan Yang Akan di Terima": {
"Pendapatan Yang di Terima": {
@@ -98,7 +98,7 @@
},
"account_number": "1130.000"
},
"account_number": "1100.0000"
"account_number": "1100.000"
},
"Aktiva Tetap": {
"Aktiva": {
@@ -121,20 +121,20 @@
"Investasi": {
"Investasi": {
"Deposito": {
"account_number": "1231.003",
"account_number": "1231.300",
"is_group": 1
},
"Investai Saham": {
"Investasi Saham": {
"Investasi Saham": {
"account_number": "1231.0011"
"account_number": "1231.101"
},
"account_number": "1231.001"
"account_number": "1231.100"
},
"Investasi Perumahan": {
"Investasi Perumahan": {
"account_number": "1231.0021"
"account_number": "1231.201"
},
"account_number": "1231.002"
"account_number": "1231.200"
},
"account_number": "1231.000"
},
@@ -142,7 +142,7 @@
},
"account_number": "1200.000"
},
"account_number": "1000.0000",
"account_number": "1000.000",
"root_type": "Asset"
},
"Beban": {
@@ -684,4 +684,4 @@
"root_type": "Income"
}
}
}
}

View File

@@ -6,6 +6,7 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe.utils import flt
from six.moves import reduce
class BankTransaction(Document):
def after_insert(self):

View File

@@ -7,6 +7,7 @@ import frappe
import json
from frappe.utils import getdate
from frappe.utils.dateutils import parse_date
from six import iteritems
@frappe.whitelist()
def upload_bank_statement():
@@ -17,11 +18,11 @@ def upload_bank_statement():
from frappe.utils.file_manager import get_uploaded_content
fname, fcontent = get_uploaded_content()
if frappe.safe_encode(fname).lower().endswith("csv"):
if frappe.safe_encode(fname).lower().endswith("csv".encode('utf-8')):
from frappe.utils.csvutils import read_csv_content
rows = read_csv_content(fcontent, False)
elif frappe.safe_encode(fname).lower().endswith("xlsx"):
elif frappe.safe_encode(fname).lower().endswith("xlsx".encode('utf-8')):
from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
rows = read_xlsx_file_from_attached_file(fcontent=fcontent)
@@ -40,19 +41,23 @@ def create_bank_entries(columns, data, bank_account):
if all(item is None for item in d) is True:
continue
fields = {}
for key, value in header_map.iteritems():
for key, value in iteritems(header_map):
fields.update({key: d[int(value)-1]})
bank_transaction = frappe.get_doc({
"doctype": "Bank Transaction"
})
bank_transaction.update(fields)
bank_transaction.date = getdate(parse_date(bank_transaction.date))
bank_transaction.bank_account = bank_account
bank_transaction.insert()
bank_transaction.submit()
count = count + 1
try:
bank_transaction = frappe.get_doc({
"doctype": "Bank Transaction"
})
bank_transaction.update(fields)
bank_transaction.date = getdate(parse_date(bank_transaction.date))
bank_transaction.bank_account = bank_account
bank_transaction.insert()
bank_transaction.submit()
count = count + 1
except Exception as e:
frappe.throw(e)
frappe.log_error(frappe.get_traceback())
return count

View File

@@ -3511,6 +3511,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "clearance_date",
"fieldtype": "Date",
"hidden": 1,
@@ -3543,6 +3544,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "col_br_payments",
"fieldtype": "Column Break",
"hidden": 0,
@@ -3880,7 +3882,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"default": "",
"fetch_if_empty": 0,
"fieldname": "allocate_advances_automatically",
"fieldtype": "Check",
@@ -4901,7 +4903,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-04-11 16:08:22.288425",
"modified": "2019-04-22 12:45:49.728359",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
@@ -5016,4 +5018,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@@ -356,6 +356,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
set_pos_data: function() {
if(this.frm.doc.is_pos) {
this.frm.set_value("allocate_advances_automatically", this.frm.doc.is_pos ? 0 : 1);
if(!this.frm.doc.company) {
this.frm.set_value("is_pos", 0);
frappe.msgprint(__("Please specify Company to proceed"));

View File

@@ -3630,7 +3630,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"default": "",
"fetch_if_empty": 0,
"fieldname": "allocate_advances_automatically",
"fieldtype": "Check",
@@ -5816,7 +5816,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-04-10 16:10:34.266458",
"modified": "2019-04-22 12:45:41.109345",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -32,7 +32,6 @@ erpnext.accounts.bankReconciliation = class BankReconciliation {
fieldname: 'company',
options: "Company",
onchange: function() {
console.log(this.value)
if (this.value) {
me.company = this.value;
} else {

View File

@@ -33,10 +33,12 @@ def reconcile(bank_transaction, payment_doctype, payment_name):
return 'reconciled'
def add_payment_to_transaction(transaction, payment_entry, gl_entry):
gl_amount, transaction_amount = (gl_entry.credit, transaction.debit) if gl_entry.credit > 0 else (gl_entry.debit, transaction.credit)
allocated_amount = gl_amount if gl_amount <= transaction_amount else transaction_amount
transaction.append("payment_entries", {
"payment_document": payment_entry.doctype,
"payment_entry": payment_entry.name,
"allocated_amount": gl_entry.credit if gl_entry.credit > 0 else gl_entry.debit
"allocated_amount": allocated_amount
})
transaction.save()
@@ -83,7 +85,7 @@ def get_linked_payments(bank_transaction):
amount_matching = check_matching_amount(bank_account[0].account, bank_account[0].company, transaction)
# Get some data from payment entries linked to a corresponding bank transaction
description_matching = get_matching_descriptions_data(bank_account[0].account, transaction)
description_matching = get_matching_descriptions_data(bank_account[0].company, transaction)
if amount_matching:
return check_amount_vs_description(amount_matching, description_matching)
@@ -207,7 +209,7 @@ def check_matching_amount(bank_account, company, transaction):
return payments
def get_matching_descriptions_data(bank_account, transaction):
def get_matching_descriptions_data(company, transaction):
if not transaction.description :
return []
@@ -243,17 +245,23 @@ def get_matching_descriptions_data(bank_account, transaction):
data = []
company_currency = get_company_currency(company)
for key, value in iteritems(links):
if key == "Payment Entry":
data.extend(frappe.get_all("Payment Entry", filters=[["name", "in", value]], fields=["'Payment Entry' as doctype", "posting_date", "party", "reference_no", "reference_date", "paid_amount"]))
data.extend(frappe.get_all("Payment Entry", filters=[["name", "in", value]], fields=["'Payment Entry' as doctype", "posting_date", "party", "reference_no", "reference_date", "paid_amount", "paid_to_account_currency as currency"]))
if key == "Journal Entry":
data.extend(frappe.get_all("Journal Entry", filters=[["name", "in", value]], fields=["'Journal Entry' as doctype", "posting_date", "paid_to_recd_from as party", "cheque_no as reference_no", "cheque_date as reference_date"]))
journal_entries = frappe.get_all("Journal Entry", filters=[["name", "in", value]], fields=["name", "'Journal Entry' as doctype", "posting_date", "paid_to_recd_from as party", "cheque_no as reference_no", "cheque_date as reference_date", "total_credit as paid_amount"])
for journal_entry in journal_entries:
journal_entry_accounts = frappe.get_all("Journal Entry Account", filters={"parenttype": journal_entry["doctype"], "parent": journal_entry["name"]}, fields=["account_currency"])
journal_entry["currency"] = journal_entry_accounts[0]["account_currency"] if journal_entry_accounts else company_currency
data.extend(journal_entries)
if key == "Sales Invoice":
data.extend(frappe.get_all("Sales Invoice", filters=[["name", "in", value]], fields=["'Sales Invoice' as doctype", "posting_date", "customer_name as party"]))
data.extend(frappe.get_all("Sales Invoice", filters=[["name", "in", value]], fields=["'Sales Invoice' as doctype", "posting_date", "customer_name as party", "paid_amount", "currency"]))
if key == "Purchase Invoice":
data.append(frappe.get_all("Purchase Invoice", filters=[["name", "in", value]], fields=["'Purchase Invoice' as doctype", "posting_date", "supplier_name as party"]))
if key == "Purchase Invoice":
data.append(frappe.get_all("Expense Claim", filters=[["name", "in", value]], fields=["'Expense Claim' as doctype", "posting_date", "employee_name as party"]))
data.extend(frappe.get_all("Purchase Invoice", filters=[["name", "in", value]], fields=["'Purchase Invoice' as doctype", "posting_date", "supplier_name as party", "paid_amount", "currency"]))
if key == "Expense Claim":
expense_claims = frappe.get_all("Expense Claim", filters=[["name", "in", value]], fields=["'Expense Claim' as doctype", "posting_date", "employee_name as party", "total_amount_reimbursed as paid_amount"])
data.extend([dict(x,**{"currency": company_currency}) for x in expense_claims])
return data
@@ -268,8 +276,8 @@ def check_amount_vs_description(amount_matching, description_matching):
result.append(am_match)
continue
if hasattr(am_match, "reference_no") and hasattr(des_match, "reference_no"):
if difflib.SequenceMatcher(lambda x: x == " ", am_match["reference_no"], des_match["reference_no"]) > 70:
if "reference_no" in am_match and "reference_no" in des_match:
if difflib.SequenceMatcher(lambda x: x == " ", am_match["reference_no"], des_match["reference_no"]).ratio() > 70:
if am_match not in result:
result.append(am_match)
if result:

View File

@@ -1,19 +1,23 @@
{
"creation": "2014-08-28 11:11:39.796473",
"custom_format": 0,
"disabled": 0,
"doc_type": "Journal Entry",
"docstatus": 0,
"doctype": "Print Format",
"html": "{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Credit Note\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n {%- for label, value in (\n (_(\"Credit To\"), doc.pay_to_recd_from),\n (_(\"Date\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Amount\"), \"<strong>\" + doc.get_formatted(\"total_amount\") + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"Remarks\"), doc.remark)\n ) -%}\n\n <div class=\"row\">\n <div class=\"col-xs-3\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-xs-9\">{{ value }}</div>\n </div>\n\n {%- endfor -%}\n\n <hr>\n <br>\n <p class=\"strong\">\n {{ _(\"For\") }} {{ doc.company }},<br>\n <br>\n <br>\n <br>\n {{ _(\"Authorized Signatory\") }}\n </p>\n</div>\n\n\n",
"idx": 2,
"modified": "2015-07-22 17:42:01.560817",
"modified_by": "Administrator",
"name": "Credit Note",
"owner": "Administrator",
"parent": "Journal Entry",
"parentfield": "__print_formats",
"parenttype": "DocType",
"print_format_type": "Server",
"align_labels_right": 0,
"creation": "2014-08-28 11:11:39.796473",
"custom_format": 0,
"disabled": 0,
"doc_type": "Journal Entry",
"docstatus": 0,
"doctype": "Print Format",
"format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"<div class=\\\"print-heading\\\">\\t\\t\\t\\t<h2>Journal Entry<br><small>{{ doc.name }}</small>\\t\\t\\t\\t</h2></div>\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"voucher_type\", \"print_hide\": 0, \"label\": \"Entry Type\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"posting_date\", \"print_hide\": 0, \"label\": \"Posting Date\"}, {\"fieldname\": \"finance_book\", \"print_hide\": 0, \"label\": \"Finance Book\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"accounts\", \"print_hide\": 0, \"label\": \"Accounting Entries\", \"visible_columns\": [{\"fieldname\": \"account\", \"print_width\": \"250px\", \"print_hide\": 0}, {\"fieldname\": \"bank_account_no\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"party_type\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"party\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"debit_in_account_currency\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"credit_in_account_currency\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"reference_type\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"reference_name\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"reference_due_date\", \"print_width\": \"\", \"print_hide\": 0}, {\"fieldname\": \"project\", \"print_width\": \"\", \"print_hide\": 0}]}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"cheque_no\", \"print_hide\": 0, \"label\": \"Reference Number\"}, {\"fieldname\": \"cheque_date\", \"print_hide\": 0, \"label\": \"Reference Date\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"get_balance\", \"print_hide\": 0, \"label\": \"Make Difference Entry\"}, {\"fieldname\": \"total_amount\", \"print_hide\": 0, \"label\": \"Total Amount\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Reference\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"clearance_date\", \"print_hide\": 0, \"label\": \"Clearance Date\"}, {\"fieldname\": \"remark\", \"print_hide\": 0, \"label\": \"Remark\"}, {\"fieldname\": \"inter_company_journal_entry_reference\", \"print_hide\": 0, \"label\": \"Inter Company Journal Entry Reference\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"due_date\", \"print_hide\": 0, \"label\": \"Due Date\"}, {\"fieldtype\": \"Section Break\", \"label\": \"Printing Settings\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"pay_to_recd_from\", \"print_hide\": 0, \"label\": \"Pay To / Recd From\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"letter_head\", \"print_hide\": 0, \"label\": \"Letter Head\"}, {\"fieldtype\": \"Section Break\", \"label\": \"More Information\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"mode_of_payment\", \"print_hide\": 0, \"label\": \"Mode of Payment\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldname\": \"stock_entry\", \"print_hide\": 0, \"label\": \"Stock Entry\"}]",
"html": "{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Credit Note\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n {%- for label, value in (\n (_(\"Credit To\"), doc.pay_to_recd_from),\n (_(\"Date\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Amount\"), \"<strong>\" + doc.get_formatted(\"total_amount\") + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"Remarks\"), doc.remark)\n ) -%}\n\n <div class=\"row\">\n <div class=\"col-xs-3\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-xs-9\">{{ value }}</div>\n </div>\n\n {%- endfor -%}\n\n <hr>\n <br>\n <p class=\"strong\">\n {{ _(\"For\") }} {{ doc.company }},<br>\n <br>\n <br>\n <br>\n {{ _(\"Authorized Signatory\") }}\n </p>\n</div>\n\n\n",
"idx": 2,
"line_breaks": 0,
"modified": "2019-04-18 12:10:14.732269",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Credit Note",
"owner": "Administrator",
"parentfield": "__print_formats",
"print_format_builder": 0,
"print_format_type": "Server",
"show_section_headings": 0,
"standard": "Yes"
}

View File

@@ -107,8 +107,8 @@
<thead>
<tr>
{% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
<th style="width: 9%">{%= __("Date") %}</th>
<th style="width: 5%">{%= __("Age (Days)") %}</th>
<th style="width: 10%">{%= __("Date") %}</th>
<th style="width: 4%">{%= __("Age (Days)") %}</th>
{% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %}
<th style="width: 16%">{%= __("Reference") %}</th>
@@ -206,7 +206,7 @@
{% if(!filters.show_pdc_in_print) { %}
<td></td>
{% } %}
{% if(report.report_name === "Accounts Receivable") { %}
{% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %}
<td></td>
{% } %}
<td></td>

View File

@@ -487,13 +487,8 @@ class ReceivablePayableReport(object):
conditions.append("company=%s")
values.append(self.filters.company)
company_finance_book = erpnext.get_default_finance_book(self.filters.company)
if not self.filters.finance_book or (self.filters.finance_book == company_finance_book):
if self.filters.finance_book:
conditions.append("ifnull(finance_book,'') in (%s, '')")
values.append(company_finance_book)
elif self.filters.finance_book:
conditions.append("ifnull(finance_book,'') = %s")
values.append(self.filters.finance_book)
if self.filters.get(party_type_field):

View File

@@ -31,11 +31,8 @@ def get_data(filters):
filters_data.append(["against_voucher", "in", assets])
company_finance_book = erpnext.get_default_finance_book(filters.get("company"))
if (not filters.get('finance_book') or (filters.get('finance_book') == company_finance_book)):
if filters.get("finance_book"):
filters_data.append(["finance_book", "in", ['', filters.get('finance_book')]])
elif filters.get("finance_book"):
filters_data.append(["finance_book", "=", filters.get('finance_book')])
gl_entries = frappe.get_all('GL Entry',
filters= filters_data,

View File

@@ -101,7 +101,7 @@ def get_income_expense_data(companies, fiscal_year, filters):
net_profit_loss = get_net_profit_loss(income, expense, companies, filters.company, company_currency, True)
return income, expense, net_profit_loss
def get_cash_flow_data(fiscal_year, companies, filters):
cash_flow_accounts = get_cash_flow_accounts()
@@ -123,7 +123,7 @@ def get_cash_flow_data(fiscal_year, companies, filters):
# add first net income in operations section
if net_profit_loss:
net_profit_loss.update({
"indent": 1,
"indent": 1,
"parent_account": cash_flow_accounts[0]['section_header']
})
data.append(net_profit_loss)
@@ -327,7 +327,7 @@ def set_gl_entries_by_account(from_date, to_date, root_lft, root_rgt, filters, g
accounts_by_name, ignore_closing_entries=False):
"""Returns a dict like { "account": [gl entries], ... }"""
company_lft, company_rgt = frappe.get_cached_value('Company',
company_lft, company_rgt = frappe.get_cached_value('Company',
filters.get('company'), ["lft", "rgt"])
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
@@ -354,7 +354,8 @@ def set_gl_entries_by_account(from_date, to_date, root_lft, root_rgt, filters, g
"to_date": to_date,
"lft": root_lft,
"rgt": root_rgt,
"company": d.name
"company": d.name,
"finance_book": filters.get("finance_book")
},
as_dict=True)
@@ -384,14 +385,8 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
if from_date:
additional_conditions.append("gl.posting_date >= %(from_date)s")
company_finance_book = erpnext.get_default_finance_book(filters.get("company"))
if not filters.get('finance_book') or (filters.get('finance_book') == company_finance_book):
additional_conditions.append("ifnull(finance_book, '') in ('%s', '')" %
frappe.db.escape(company_finance_book))
elif filters.get("finance_book"):
additional_conditions.append("ifnull(finance_book, '') = '%s' " %
frappe.db.escape(filters.get("finance_book")))
if filters.get("finance_book"):
additional_conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')")
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""

View File

@@ -184,12 +184,8 @@ class PartyLedgerSummaryReport(object):
if self.filters.company:
conditions.append("gle.company=%(company)s")
self.filters.company_finance_book = erpnext.get_default_finance_book(self.filters.company)
if not self.filters.finance_book or (self.filters.finance_book == self.filters.company_finance_book):
conditions.append("ifnull(finance_book,'') in (%(company_finance_book)s, '')")
elif self.filters.finance_book:
conditions.append("ifnull(finance_book,'') = %(finance_book)s")
if self.filters.finance_book:
conditions.append("ifnull(finance_book,'') in (%(finance_book)s, '')")
if self.filters.get("party"):
conditions.append("party=%(party)s")

View File

@@ -392,14 +392,8 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
filters.cost_center = get_cost_centers_with_children(filters.cost_center)
additional_conditions.append("cost_center in %(cost_center)s")
company_finance_book = erpnext.get_default_finance_book(filters.get("company"))
if not filters.get('finance_book') or (filters.get('finance_book') == company_finance_book):
additional_conditions.append("ifnull(finance_book, '') in ('%s', '')" %
frappe.db.escape(company_finance_book))
elif filters.get("finance_book"):
additional_conditions.append("ifnull(finance_book, '') = '%s' " %
frappe.db.escape(filters.get("finance_book")))
if filters.get("finance_book"):
additional_conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')")
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""

View File

@@ -186,12 +186,8 @@ def get_conditions(filters):
if filters.get("project"):
conditions.append("project in %(project)s")
company_finance_book = erpnext.get_default_finance_book(filters.get("company"))
if not filters.get("finance_book") or (filters.get("finance_book") == company_finance_book):
filters['finance_book'] = company_finance_book
if filters.get("finance_book"):
conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')")
elif filters.get("finance_book"):
conditions.append("ifnull(finance_book, '') = %(finance_book)s")
from frappe.desk.reportview import build_match_conditions
match_conditions = build_match_conditions("GL Entry")

View File

@@ -23,6 +23,12 @@ frappe.query_reports["Gross Profit"] = {
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_end_date")
},
{
"fieldname":"sales_invoice",
"label": __("Sales Invoice"),
"fieldtype": "Link",
"options": "Sales Invoice"
},
{
"fieldname":"group_by",
"label": __("Group By"),

View File

@@ -302,6 +302,12 @@ class GrossProfitGenerator(object):
sales_person_cols = ""
sales_team_table = ""
if self.filters.get("sales_invoice"):
conditions += " and `tabSales Invoice`.name = %(sales_invoice)s"
if self.filters.get("item_code"):
conditions += " and `tabSales Invoice Item`.item_code = %(item_code)s"
self.si_list = frappe.db.sql("""
select
`tabSales Invoice Item`.parenttype, `tabSales Invoice Item`.parent,

View File

@@ -1,23 +1,27 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-12-27 16:15:52.615453",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2017-12-27 16:46:54.422356",
"modified": "2019-04-19 10:50:36.061588",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Share Ledger",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Share Transfer",
"report_name": "Share Ledger",
"report_type": "Script Report",
"roles": [
{
"role": "Administrator"
},
{
"role": "System Manager"
}
]
}

View File

@@ -112,13 +112,15 @@ def convert_to_presentation_currency(gl_entries, currency_info):
if entry.get('debit'):
entry['debit'] = converted_value
else:
if entry.get('credit'):
entry['credit'] = converted_value
elif account_currency == presentation_currency:
if entry.get('debit'):
entry['debit'] = debit_in_account_currency
else:
if entry.get('credit'):
entry['credit'] = credit_in_account_currency
converted_gl_list.append(entry)
@@ -133,3 +135,22 @@ def get_appropriate_company(filters):
company = get_default_company()
return company
@frappe.whitelist()
def get_invoiced_item_gross_margin(sales_invoice=None, item_code=None, company=None):
from erpnext.accounts.report.gross_profit.gross_profit import GrossProfitGenerator
sales_invoice = sales_invoice or frappe.form_dict.get('sales_invoice')
item_code = item_code or frappe.form_dict.get('item_code')
company = company or frappe.get_cached_value("Sales Invoice", sales_invoice, 'company')
filters = {
'sales_invoice': sales_invoice,
'item_code': item_code,
'company': company,
'group_by': 'Invoice'
}
gross_profit_data = GrossProfitGenerator(filters)
return gross_profit_data.grouped_data

View File

@@ -395,7 +395,7 @@ def make_purchase_invoice(source_name, target_doc=None):
or item.get("buying_cost_center")
or item_group.get("buying_cost_center"))
doc = get_mapped_doc("Purchase Order", source_name, {
fields = {
"Purchase Order": {
"doctype": "Purchase Invoice",
"field_map": {
@@ -419,7 +419,15 @@ def make_purchase_invoice(source_name, target_doc=None):
"doctype": "Purchase Taxes and Charges",
"add_if_empty": True
}
}, target_doc, postprocess)
}
if frappe.get_single("Accounts Settings").automatically_fetch_payment_terms == 1:
fields["Payment Schedule"] = {
"doctype": "Payment Schedule",
"add_if_empty": True
}
doc = get_mapped_doc("Purchase Order", source_name, fields, target_doc, postprocess)
return doc

View File

@@ -6,7 +6,7 @@ import unittest
import frappe
import frappe.defaults
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
from frappe.utils import flt, add_days, nowdate
from frappe.utils import flt, add_days, nowdate, getdate
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.buying.doctype.purchase_order.purchase_order import (make_purchase_receipt, make_purchase_invoice, make_rm_stock_entry as make_subcontract_transfer_entry)
from erpnext.stock.doctype.material_request.test_material_request import make_material_request
@@ -133,9 +133,9 @@ class TestPurchaseOrder(unittest.TestCase):
po.submit()
self.assertEqual(po.payment_schedule[0].payment_amount, 2500.0)
self.assertEqual(po.payment_schedule[0].due_date, po.transaction_date)
self.assertEqual(getdate(po.payment_schedule[0].due_date), getdate(po.transaction_date))
self.assertEqual(po.payment_schedule[1].payment_amount, 2500.0)
self.assertEqual(po.payment_schedule[1].due_date, add_days(po.transaction_date, 30))
self.assertEqual(getdate(po.payment_schedule[1].due_date), add_days(getdate(po.transaction_date), 30))
pi = make_purchase_invoice(po.name)
pi.save()
@@ -143,9 +143,9 @@ class TestPurchaseOrder(unittest.TestCase):
self.assertEqual(len(pi.get("items", [])), 1)
self.assertEqual(pi.payment_schedule[0].payment_amount, 2500.0)
self.assertEqual(pi.payment_schedule[0].due_date, po.transaction_date)
self.assertEqual(getdate(pi.payment_schedule[0].due_date), getdate(po.transaction_date))
self.assertEqual(pi.payment_schedule[1].payment_amount, 2500.0)
self.assertEqual(pi.payment_schedule[1].due_date, add_days(po.transaction_date, 30))
self.assertEqual(getdate(pi.payment_schedule[1].due_date), add_days(getdate(po.transaction_date), 30))
def test_subcontracting(self):
po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes")
@@ -294,6 +294,10 @@ class TestPurchaseOrder(unittest.TestCase):
make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100)
make_stock_entry(target="_Test Warehouse - _TC", item_code="_Test Item Home Desktop 100",
qty=20, basic_rate=100)
make_stock_entry(target="_Test Warehouse 1 - _TC", item_code="_Test Item",
qty=30, basic_rate=100)
make_stock_entry(target="_Test Warehouse 1 - _TC", item_code="_Test Item Home Desktop 100",
qty=30, basic_rate=100)
bin1 = frappe.db.get_value("Bin",
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},

View File

@@ -1,18 +1,19 @@
{
"add_total_row": 1,
"apply_user_permissions": 1,
"creation": "2013-05-13 16:10:02",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 3,
"is_standard": "Yes",
"modified": "2017-02-24 20:10:53.005589",
"modified": "2019-04-19 14:54:49.123836",
"modified_by": "Administrator",
"module": "Buying",
"name": "Requested Items To Be Ordered",
"owner": "Administrator",
"query": "select \n mr.name as \"Material Request:Link/Material Request:120\",\n\tmr.transaction_date as \"Date:Date:100\",\n\tmr_item.item_code as \"Item Code:Link/Item:120\",\n\tsum(ifnull(mr_item.qty, 0)) as \"Qty:Float:100\",\n\tsum(ifnull(mr_item.ordered_qty, 0)) as \"Ordered Qty:Float:100\", \n\t(sum(mr_item.qty) - sum(ifnull(mr_item.ordered_qty, 0))) as \"Qty to Order:Float:100\",\n\tmr_item.item_name as \"Item Name::150\",\n\tmr_item.description as \"Description::200\",\n\tmr.company as \"Company:Link/Company:\"\nfrom\n\t`tabMaterial Request` mr, `tabMaterial Request Item` mr_item\nwhere\n\tmr_item.parent = mr.name\n\tand mr.material_request_type = \"Purchase\"\n\tand mr.docstatus = 1\n\tand mr.status != \"Stopped\"\ngroup by mr.name, mr_item.item_code\nhaving\n\tsum(ifnull(mr_item.ordered_qty, 0)) < sum(ifnull(mr_item.qty, 0))\norder by mr.transaction_date asc",
"prepared_report": 0,
"query": "select \n mr.name as \"Material Request:Link/Material Request:120\",\n\tmr.transaction_date as \"Date:Date:100\",\n\tmr_item.item_code as \"Item Code:Link/Item:120\",\n\tsum(ifnull(mr_item.stock_qty, 0)) as \"Qty:Float:100\",\n\tifnull(mr_item.stock_uom, '') as \"UOM:Link/UOM:100\",\n\tsum(ifnull(mr_item.ordered_qty, 0)) as \"Ordered Qty:Float:100\", \n\t(sum(mr_item.stock_qty) - sum(ifnull(mr_item.ordered_qty, 0))) as \"Qty to Order:Float:100\",\n\tmr_item.item_name as \"Item Name::150\",\n\tmr_item.description as \"Description::200\",\n\tmr.company as \"Company:Link/Company:\"\nfrom\n\t`tabMaterial Request` mr, `tabMaterial Request Item` mr_item\nwhere\n\tmr_item.parent = mr.name\n\tand mr.material_request_type = \"Purchase\"\n\tand mr.docstatus = 1\n\tand mr.status != \"Stopped\"\ngroup by mr.name, mr_item.item_code\nhaving\n\tsum(ifnull(mr_item.ordered_qty, 0)) < sum(ifnull(mr_item.stock_qty, 0))\norder by mr.transaction_date asc",
"ref_doctype": "Purchase Order",
"report_name": "Requested Items To Be Ordered",
"report_type": "Query Report",

View File

@@ -27,6 +27,11 @@ def get_data():
"type": "doctype",
"name": "Payment Entry",
"description": _("Bank/Cash transactions against party or for internal transfer")
},
{
"type": "doctype",
"name": "Payment Term",
"description": _("Payment Terms based on conditions")
}
]
@@ -284,6 +289,11 @@ def get_data():
"name": "Currency Exchange",
"description": _("Currency exchange rate master.")
},
{
"type": "doctype",
"name": "Exchange Rate Revaluation",
"description": _("Exchange Rate Revaluation master.")
},
{
"type": "doctype",
"name": "Payment Gateway Account",

View File

@@ -30,9 +30,8 @@ class AccountsController(TransactionBase):
return self.__company_currency
def onload(self):
if self.get("__onload"):
self.get("__onload").make_payment_via_journal_entry \
= frappe.db.get_single_value('Accounts Settings', 'make_payment_via_journal_entry')
self.set_onload("make_payment_via_journal_entry",
frappe.db.get_single_value('Accounts Settings', 'make_payment_via_journal_entry'))
if self.is_new():
relevant_docs = ("Quotation", "Purchase Order", "Sales Order",
@@ -89,7 +88,7 @@ class AccountsController(TransactionBase):
self.validate_paid_amount()
if self.doctype in ['Purchase Invoice', 'Sales Invoice']:
if cint(self.allocate_advances_automatically):
if cint(self.allocate_advances_automatically) and not cint(self.is_pos):
self.set_advances()
if self.is_return:

View File

@@ -34,8 +34,8 @@ status_map = {
],
"Sales Order": [
["Draft", None],
["To Deliver and Bill", "eval:self.per_delivered < 100 and self.per_billed < 100 and self.docstatus == 1"],
["To Bill", "eval:self.per_delivered == 100 and self.per_billed < 100 and self.docstatus == 1"],
["To Deliver and Bill", "eval:self.per_delivered < 100 and self.per_billed < 100 and self.docstatus == 1 and self.order_type in ['Sales', 'Shopping Cart']"],
["To Bill", "eval:self.per_delivered == 100 or self.order_type == 'Maintenance' and self.per_billed < 100 and self.docstatus == 1"],
["To Deliver", "eval:self.per_delivered < 100 and self.per_billed == 100 and self.docstatus == 1"],
["Completed", "eval:self.per_delivered == 100 and self.per_billed == 100 and self.docstatus == 1"],
["Completed", "eval:self.order_type == 'Maintenance' and self.per_billed == 100 and self.docstatus == 1"],

View File

@@ -10,6 +10,7 @@ from frappe.model.mapper import get_mapped_doc
from erpnext.controllers.selling_controller import SellingController
from frappe.contacts.address_and_contact import load_address_and_contact
from erpnext.accounts.party import set_taxes
from frappe.email.inbox import link_communication_to_document
sender_field = "email_id"
@@ -185,7 +186,7 @@ def get_lead_details(lead, posting_date=None, company=None):
out.update({
"territory": lead.territory,
"customer_name": lead.company_name or lead.lead_name,
"contact_display": lead.lead_name,
"contact_display": " ".join(filter(None, [lead.salutation, lead.lead_name])),
"contact_email": lead.email_id,
"contact_mobile": lead.mobile_no,
"contact_phone": lead.phone,
@@ -199,3 +200,29 @@ def get_lead_details(lead, posting_date=None, company=None):
out['taxes_and_charges'] = taxes_and_charges
return out
@frappe.whitelist()
def make_lead_from_communication(communication, ignore_communication_links=False):
""" raise a issue from email """
doc = frappe.get_doc("Communication", communication)
lead_name = None
if doc.sender:
lead_name = frappe.db.get_value("Lead", {"email_id": doc.sender})
if not lead_name and doc.phone_no:
lead_name = frappe.db.get_value("Lead", {"mobile_no": doc.phone_no})
if not lead_name:
lead = frappe.get_doc({
"doctype": "Lead",
"lead_name": doc.sender_full_name,
"email_id": doc.sender,
"mobile_no": doc.phone_no
})
lead.flags.ignore_mandatory = True
lead.flags.ignore_permissions = True
lead.insert()
lead_name = lead.name
link_communication_to_document(doc, "Lead", lead_name, ignore_communication_links)
return lead_name

View File

@@ -9,6 +9,7 @@ from frappe.model.mapper import get_mapped_doc
from erpnext.setup.utils import get_exchange_rate
from erpnext.utilities.transaction_base import TransactionBase
from erpnext.accounts.party import get_party_account_currency
from frappe.email.inbox import link_communication_to_document
subject_field = "title"
sender_field = "contact_email"
@@ -318,3 +319,24 @@ def auto_close_opportunity():
doc.flags.ignore_permissions = True
doc.flags.ignore_mandatory = True
doc.save()
@frappe.whitelist()
def make_opportunity_from_communication(communication, ignore_communication_links=False):
from erpnext.crm.doctype.lead.lead import make_lead_from_communication
doc = frappe.get_doc("Communication", communication)
lead = doc.reference_name if doc.reference_doctype == "Lead" else None
if not lead:
lead = make_lead_from_communication(communication, ignore_communication_links=True)
enquiry_from = "Lead"
opportunity = frappe.get_doc({
"doctype": "Opportunity",
"enquiry_from": enquiry_from,
"lead": lead
}).insert(ignore_permissions=True)
link_communication_to_document(doc, "Opportunity", opportunity.name, ignore_communication_links)
return opportunity.name

View File

@@ -4,24 +4,70 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt
def execute(filters=None):
columns, data = [], []
columns=get_columns()
data=get_lead_data(filters, "Campaign Name")
columns=get_columns("Campaign Name")
data=get_lead_data(filters or {}, "Campaign Name")
return columns, data
def get_columns():
def get_columns(based_on):
return [
_("Campaign Name") + ":data:130",
_("Lead Count") + ":Int:80",
_("Opp Count") + ":Int:80",
_("Quot Count") + ":Int:80",
_("Order Count") + ":Int:100",
_("Order Value") + ":Float:100",
_("Opp/Lead %") + ":Float:100",
_("Quot/Lead %") + ":Float:100",
_("Order/Quot %") + ":Float:100"
{
"fieldname": frappe.scrub(based_on),
"label": _(based_on),
"fieldtype": "Data",
"width": 150
},
{
"fieldname": "lead_count",
"label": _("Lead Count"),
"fieldtype": "Int",
"width": 80
},
{
"fieldname": "opp_count",
"label": _("Opp Count"),
"fieldtype": "Int",
"width": 80
},
{
"fieldname": "quot_count",
"label": _("Quot Count"),
"fieldtype": "Int",
"width": 80
},
{
"fieldname": "order_count",
"label": _("Order Count"),
"fieldtype": "Int",
"width": 100
},
{
"fieldname": "order_value",
"label": _("Order Value"),
"fieldtype": "Float",
"width": 100
},
{
"fieldname": "opp_lead",
"label": _("Opp/Lead %"),
"fieldtype": "Float",
"width": 100
},
{
"fieldname": "quot_lead",
"label": _("Quot/Lead %"),
"fieldtype": "Float",
"width": 100
},
{
"fieldname": "order_quot",
"label": _("Order/Quot %"),
"fieldtype": "Float",
"width": 100
}
]
def get_lead_data(filters, based_on):
@@ -41,18 +87,18 @@ def get_lead_data(filters, based_on):
data = []
for based_on_value, leads in lead_map.items():
row = {
based_on: based_on_value,
"Lead Count": len(leads)
based_on_field: based_on_value,
"lead_count": len(leads)
}
row["Quot Count"]= get_lead_quotation_count(leads)
row["Opp Count"] = get_lead_opp_count(leads)
row["Order Count"] = get_quotation_ordered_count(leads)
row["Order Value"] = get_order_amount(leads)
row["quot_count"]= get_lead_quotation_count(leads)
row["opp_count"] = get_lead_opp_count(leads)
row["order_count"] = get_quotation_ordered_count(leads)
row["order_value"] = get_order_amount(leads) or 0
row["Opp/Lead %"] = row["Opp Count"] / row["Lead Count"] * 100
row["Quot/Lead %"] = row["Quot Count"] / row["Lead Count"] * 100
row["opp_lead"] = flt(row["opp_count"]) / flt(row["lead_count"] or 1.0) * 100.0
row["quot_lead"] = flt(row["quot_count"]) / flt(row["lead_count"] or 1.0) * 100.0
row["Order/Quot %"] = row["Order Count"] / (row["Quot Count"] or 1) * 100
row["order_quot"] = flt(row["order_count"]) / flt(row["quot_count"] or 1.0) * 100.0
data.append(row)

View File

@@ -51,7 +51,7 @@ def get_additional_salary_component(employee, start_date, end_date):
for d in additional_components:
component = frappe.get_doc("Salary Component", d.salary_component)
struct_row = {'salary_component': d.salary_component}
for field in ["depends_on_lwp", "abbr", "is_tax_applicable", "variable_based_on_taxable_salary", "is_additional_component"]:
for field in ["depends_on_payment_days", "abbr", "is_tax_applicable", "variable_based_on_taxable_salary", "is_additional_component"]:
struct_row[field] = component.get(field)
additional_components_list.append({

View File

@@ -80,6 +80,14 @@ class Employee(NestedSet):
if not self.create_user_permission: return
if not has_permission('User Permission', ptype='write'): return
employee_user_permission_exists = frappe.db.exists('User Permission', {
'allow': 'Employee',
'for_value': self.name,
'user': self.user_id
})
if employee_user_permission_exists: return
add_user_permission("Employee", self.name, self.user_id)
set_user_permission_if_allowed("Company", self.company, self.user_id)

View File

@@ -113,7 +113,7 @@ def get_max_benefits(employee, on_date):
def get_max_benefits_remaining(employee, on_date, payroll_period):
max_benefits = get_max_benefits(employee, on_date)
if max_benefits and max_benefits > 0:
have_depends_on_lwp = False
have_depends_on_payment_days = False
per_day_amount_total = 0
payroll_period_days = get_payroll_period_days(on_date, on_date, employee)[0]
payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period)
@@ -122,22 +122,22 @@ def get_max_benefits_remaining(employee, on_date, payroll_period):
prev_sal_slip_flexi_total = get_sal_slip_total_benefit_given(employee, payroll_period_obj)
if prev_sal_slip_flexi_total > 0:
# Check salary structure hold depends_on_lwp component
# Check salary structure hold depends_on_payment_days component
# If yes then find the amount per day of each component and find the sum
sal_struct_name = get_assigned_salary_structure(employee, on_date)
if sal_struct_name:
sal_struct = frappe.get_doc("Salary Structure", sal_struct_name)
for sal_struct_row in sal_struct.get("earnings"):
salary_component = frappe.get_doc("Salary Component", sal_struct_row.salary_component)
if salary_component.depends_on_lwp == 1 and salary_component.pay_against_benefit_claim != 1:
have_depends_on_lwp = True
if salary_component.depends_on_payment_days == 1 and salary_component.pay_against_benefit_claim != 1:
have_depends_on_payment_days = True
benefit_amount = get_benefit_pro_rata_ratio_amount(sal_struct, salary_component.max_benefit_amount)
amount_per_day = benefit_amount / payroll_period_days
per_day_amount_total += amount_per_day
# Then the sum multiply with the no of lwp in that period
# Include that amount to the prev_sal_slip_flexi_total to get the actual
if have_depends_on_lwp and per_day_amount_total > 0:
if have_depends_on_payment_days and per_day_amount_total > 0:
holidays = get_holidays_for_employee(employee, payroll_period_obj.start_date, on_date)
working_days = date_diff(on_date, payroll_period_obj.start_date) + 1
leave_days = calculate_lwp(employee, payroll_period_obj.start_date, holidays, working_days)
@@ -185,7 +185,7 @@ def get_benefit_component_amount(employee, start_date, end_date, struct_row, sal
'payroll_period': payroll_period
})
if frappe.db.get_value("Salary Component", struct_row.salary_component, "depends_on_lwp") != 1:
if frappe.db.get_value("Salary Component", struct_row.salary_component, "depends_on_payment_days") != 1:
if frequency == "Monthly" and actual_payroll_days in range(360, 370):
period_length = 1
period_factor = 12

View File

@@ -170,7 +170,7 @@ def get_last_payroll_period_benefits(employee, sal_slip_start_date, sal_slip_end
amount += current_claimed_amount
struct_row = {}
salary_components_dict = {}
struct_row['depends_on_lwp'] = salary_component.depends_on_lwp
struct_row['depends_on_payment_days'] = salary_component.depends_on_payment_days
struct_row['salary_component'] = salary_component.name
struct_row['abbr'] = salary_component.salary_component_abbr
struct_row['do_not_include_in_total'] = salary_component.do_not_include_in_total

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
@@ -20,6 +21,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "employee",
"fieldtype": "Link",
"hidden": 0,
@@ -54,6 +56,7 @@
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.company",
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -87,6 +90,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
@@ -118,6 +122,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "payroll_period",
"fieldtype": "Link",
"hidden": 0,
@@ -151,6 +156,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_exemption_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -184,6 +190,7 @@
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.department",
"fetch_if_empty": 0,
"fieldname": "department",
"fieldtype": "Link",
"hidden": 0,
@@ -217,6 +224,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -249,6 +257,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_8",
"fieldtype": "Section Break",
"hidden": 0,
@@ -280,6 +289,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "declarations",
"fieldtype": "Table",
"hidden": 0,
@@ -300,7 +310,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
@@ -317,7 +327,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-08-21 16:15:49.363307",
"modified": "2019-04-23 15:50:48.693555",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Tax Exemption Declaration",

View File

@@ -135,6 +135,7 @@ class LeaveApplication(Document):
date = dt.strftime("%Y-%m-%d")
doc = frappe.new_doc("Attendance")
doc.employee = self.employee
doc.employee_name = self.employee_name
doc.attendance_date = date
doc.company = self.company
doc.leave_type = self.leave_type

View File

@@ -75,5 +75,5 @@ var set_value_for_condition_and_formula = function(frm) {
frm.set_value("amount_based_on_formula", 0);
frm.set_value("statistical_component", 0);
frm.set_value("do_not_include_in_total", 0);
frm.set_value("depends_on_lwp", 0);
frm.set_value("depends_on_payment_days", 0);
};

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
@@ -19,6 +20,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "salary_component",
"fieldtype": "Data",
"hidden": 0,
@@ -51,6 +53,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "salary_component_abbr",
"fieldtype": "Data",
"hidden": 0,
@@ -85,6 +88,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "type",
"fieldtype": "Select",
"hidden": 0,
@@ -119,6 +123,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_flexible_benefit != 1",
"fetch_if_empty": 0,
"fieldname": "is_additional_component",
"fieldtype": "Check",
"hidden": 0,
@@ -153,6 +158,7 @@
"columns": 0,
"default": "1",
"depends_on": "eval:doc.type == \"Earning\"",
"fetch_if_empty": 0,
"fieldname": "is_tax_applicable",
"fieldtype": "Check",
"hidden": 0,
@@ -186,6 +192,7 @@
"collapsible": 0,
"columns": 0,
"default": "1",
"fetch_if_empty": 0,
"fieldname": "is_payable",
"fieldtype": "Check",
"hidden": 0,
@@ -218,7 +225,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "depends_on_lwp",
"default": "1",
"fetch_if_empty": 0,
"fieldname": "depends_on_payment_days",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -227,7 +236,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Depends on Leave Without Pay",
"label": "Depends on Payment Days",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -250,6 +259,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "do_not_include_in_total",
"fieldtype": "Check",
"hidden": 0,
@@ -282,6 +292,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
@@ -313,6 +324,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "disabled",
"fieldtype": "Check",
"hidden": 0,
@@ -345,6 +357,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "description",
"fieldtype": "Small Text",
"hidden": 0,
@@ -378,6 +391,7 @@
"collapsible": 0,
"columns": 0,
"description": "If selected, the value specified or calculated in this component will not contribute to the earnings or deductions. However, it's value can be referenced by other components that can be added or deducted. ",
"fetch_if_empty": 0,
"fieldname": "statistical_component",
"fieldtype": "Check",
"hidden": 0,
@@ -411,6 +425,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.type==\"Earning\" && doc.is_additional_component != 1 && doc.statistical_component!=1",
"fetch_if_empty": 0,
"fieldname": "flexible_benefits",
"fieldtype": "Section Break",
"hidden": 0,
@@ -444,6 +459,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_additional_component != 1",
"fetch_if_empty": 0,
"fieldname": "is_flexible_benefit",
"fieldtype": "Check",
"hidden": 0,
@@ -477,6 +493,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "is_flexible_benefit",
"fetch_if_empty": 0,
"fieldname": "max_benefit_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -509,6 +526,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_9",
"fieldtype": "Column Break",
"hidden": 0,
@@ -541,6 +559,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "is_flexible_benefit",
"fetch_if_empty": 0,
"fieldname": "pay_against_benefit_claim",
"fieldtype": "Check",
"hidden": 0,
@@ -574,6 +593,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_flexible_benefit == 1 & doc.create_separate_payment_entry_against_benefit_claim !=1",
"fetch_if_empty": 0,
"fieldname": "only_tax_impact",
"fieldtype": "Check",
"hidden": 0,
@@ -607,6 +627,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_flexible_benefit == 1 & doc.only_tax_impact !=1",
"fetch_if_empty": 0,
"fieldname": "create_separate_payment_entry_against_benefit_claim",
"fieldtype": "Check",
"hidden": 0,
@@ -640,6 +661,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.type=='Deduction'",
"fetch_if_empty": 0,
"fieldname": "section_break_11",
"fieldtype": "Section Break",
"hidden": 0,
@@ -671,6 +693,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "variable_based_on_taxable_salary",
"fieldtype": "Check",
"hidden": 0,
@@ -704,6 +727,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.statistical_component != 1",
"fetch_if_empty": 0,
"fieldname": "section_break_5",
"fieldtype": "Section Break",
"hidden": 0,
@@ -736,6 +760,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "accounts",
"fieldtype": "Table",
"hidden": 0,
@@ -771,6 +796,7 @@
"collapsible_depends_on": "",
"columns": 0,
"depends_on": "eval:doc.is_flexible_benefit != 1 && doc.variable_based_on_taxable_salary != 1",
"fetch_if_empty": 0,
"fieldname": "condition_and_formula",
"fieldtype": "Section Break",
"hidden": 0,
@@ -803,6 +829,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "condition",
"fieldtype": "Code",
"hidden": 0,
@@ -836,6 +863,7 @@
"collapsible": 0,
"columns": 0,
"default": "",
"fetch_if_empty": 0,
"fieldname": "amount_based_on_formula",
"fieldtype": "Check",
"hidden": 0,
@@ -869,6 +897,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.amount_based_on_formula!==0",
"fetch_if_empty": 0,
"fieldname": "formula",
"fieldtype": "Code",
"hidden": 0,
@@ -902,6 +931,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.amount_based_on_formula!==1",
"fetch_if_empty": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -934,6 +964,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_28",
"fieldtype": "Column Break",
"hidden": 0,
@@ -965,6 +996,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "help",
"fieldtype": "HTML",
"hidden": 0,
@@ -1003,7 +1035,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-09-20 16:44:58.876044",
"modified": "2019-04-16 19:08:55.323567",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Component",

View File

@@ -19,6 +19,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "salary_component",
"fieldtype": "Link",
"hidden": 0,
@@ -55,6 +56,7 @@
"default": "",
"depends_on": "eval:doc.parenttype=='Salary Structure'",
"fetch_from": "salary_component.salary_component_abbr",
"fetch_if_empty": 0,
"fieldname": "abbr",
"fieldtype": "Data",
"hidden": 0,
@@ -88,6 +90,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
@@ -121,6 +124,7 @@
"columns": 0,
"description": "If selected, the value specified or calculated in this component will not contribute to the earnings or deductions. However, it's value can be referenced by other components that can be added or deducted. ",
"fetch_from": "salary_component.statistical_component",
"fetch_if_empty": 0,
"fieldname": "statistical_component",
"fieldtype": "Check",
"hidden": 0,
@@ -154,6 +158,7 @@
"collapsible": 0,
"columns": 0,
"fetch_from": "salary_component.is_tax_applicable",
"fetch_if_empty": 0,
"fieldname": "is_tax_applicable",
"fieldtype": "Check",
"hidden": 0,
@@ -187,6 +192,7 @@
"collapsible": 0,
"columns": 0,
"fetch_from": "salary_component.is_flexible_benefit",
"fetch_if_empty": 0,
"fieldname": "is_flexible_benefit",
"fieldtype": "Check",
"hidden": 0,
@@ -221,6 +227,7 @@
"columns": 0,
"default": "",
"fetch_from": "salary_component.is_additional_component",
"fetch_if_empty": 0,
"fieldname": "is_additional_component",
"fieldtype": "Check",
"hidden": 1,
@@ -255,6 +262,7 @@
"columns": 0,
"default": "",
"fetch_from": "salary_component.variable_based_on_taxable_salary",
"fetch_if_empty": 0,
"fieldname": "variable_based_on_taxable_salary",
"fieldtype": "Check",
"hidden": 0,
@@ -288,8 +296,9 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_from": "salary_component.depends_on_lwp",
"fieldname": "depends_on_lwp",
"fetch_from": "salary_component.depends_on_payment_days",
"fetch_if_empty": 0,
"fieldname": "depends_on_payment_days",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -298,7 +307,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Depends on Leave Without Pay",
"label": "Depends on Payment Days",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -322,6 +331,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_flexible_benefit != 1",
"fetch_if_empty": 0,
"fieldname": "section_break_2",
"fieldtype": "Section Break",
"hidden": 0,
@@ -354,6 +364,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.parenttype=='Salary Structure'",
"fetch_if_empty": 0,
"fieldname": "condition",
"fieldtype": "Code",
"hidden": 0,
@@ -389,6 +400,7 @@
"default": "0",
"depends_on": "eval:doc.parenttype=='Salary Structure'",
"fetch_from": "",
"fetch_if_empty": 0,
"fieldname": "amount_based_on_formula",
"fieldtype": "Check",
"hidden": 0,
@@ -425,6 +437,7 @@
"default": "",
"depends_on": "eval:doc.amount_based_on_formula!==0 && doc.parenttype==='Salary Structure'",
"description": "",
"fetch_if_empty": 0,
"fieldname": "formula",
"fieldtype": "Code",
"hidden": 0,
@@ -458,6 +471,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.amount_based_on_formula!==1 || doc.parenttype==='Salary Slip'",
"fetch_if_empty": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -491,6 +505,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "do_not_include_in_total",
"fieldtype": "Check",
"hidden": 0,
@@ -524,6 +539,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.parenttype=='Salary Structure'",
"fetch_if_empty": 0,
"fieldname": "default_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -558,6 +574,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.parenttype=='Salary Slip' && doc.parentfield=='deductions' && doc.variable_based_on_taxable_salary == 1",
"fetch_if_empty": 0,
"fieldname": "tax_on_flexible_benefit",
"fieldtype": "Currency",
"hidden": 0,
@@ -591,6 +608,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.parenttype=='Salary Slip' && doc.parentfield=='deductions' && doc.variable_based_on_taxable_salary == 1",
"fetch_if_empty": 0,
"fieldname": "tax_on_additional_salary",
"fieldtype": "Currency",
"hidden": 0,
@@ -624,6 +642,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.parenttype=='Salary Structure'",
"fetch_if_empty": 0,
"fieldname": "section_break_11",
"fieldtype": "Column Break",
"hidden": 0,
@@ -656,6 +675,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.parenttype=='Salary Structure'",
"fetch_if_empty": 0,
"fieldname": "condition_and_formula_help",
"fieldtype": "HTML",
"hidden": 0,
@@ -693,7 +713,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-02-04 14:41:56.030991",
"modified": "2019-04-16 19:09:31.726597",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Detail",

View File

@@ -132,9 +132,6 @@ var get_emp_and_leave_details = function(doc, dt, dn) {
});
}
cur_frm.cscript.employee = function(doc,dt,dn){
get_emp_and_leave_details(doc, dt, dn);
}
cur_frm.cscript.leave_without_pay = function(doc,dt,dn){
if (doc.employee && doc.start_date && doc.end_date) {
@@ -160,7 +157,7 @@ cur_frm.cscript.amount = function(doc,dt,dn){
calculate_all(doc, dt, dn);
}
cur_frm.cscript.depends_on_lwp = function(doc,dt,dn){
cur_frm.cscript.depends_on_payment_days = function(doc,dt,dn){
calculate_earning_total(doc, dt, dn, true);
calculate_ded_total(doc, dt, dn, true);
calculate_net_pay(doc, dt, dn);
@@ -174,7 +171,7 @@ var calculate_earning_total = function(doc, dt, dn, reset_amount) {
var tbl = doc.earnings || [];
var total_earn = 0;
for(var i = 0; i < tbl.length; i++){
if(cint(tbl[i].depends_on_lwp) == 1) {
if(cint(tbl[i].depends_on_payment_days) == 1) {
tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days) /
cint(doc.total_working_days)*100)/100;
} else if(reset_amount && tbl[i].default_amount) {
@@ -196,7 +193,7 @@ var calculate_ded_total = function(doc, dt, dn, reset_amount) {
var tbl = doc.deductions || [];
var total_ded = 0;
for(var i = 0; i < tbl.length; i++){
if(cint(tbl[i].depends_on_lwp) == 1) {
if(cint(tbl[i].depends_on_payment_days) == 1) {
tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days)/cint(doc.total_working_days)*100)/100;
} else if(reset_amount && tbl[i].default_amount) {
tbl[i].amount = tbl[i].default_amount;
@@ -209,16 +206,12 @@ var calculate_ded_total = function(doc, dt, dn, reset_amount) {
refresh_many(['deductions', 'total_deduction']);
}
// Calculate net payable amount
// ------------------------------------------------------------------------
var calculate_net_pay = function(doc, dt, dn) {
doc.net_pay = flt(doc.gross_pay) - flt(doc.total_deduction);
doc.rounded_total = Math.round(doc.net_pay);
refresh_many(['net_pay', 'rounded_total']);
}
// validate
// ------------------------------------------------------------------------
cur_frm.cscript.validate = function(doc, dt, dn) {
calculate_all(doc, dt, dn);
}

View File

@@ -131,11 +131,12 @@ class SalarySlip(TransactionBase):
for d in self.get(key):
if d.salary_component == struct_row.salary_component:
component_row = d
if not component_row:
self.append(key, {
'amount': amount,
'default_amount': amount,
'depends_on_lwp' : struct_row.depends_on_lwp,
'depends_on_payment_days' : struct_row.depends_on_payment_days,
'salary_component' : struct_row.salary_component,
'abbr' : struct_row.abbr,
'do_not_include_in_total' : struct_row.do_not_include_in_total,
@@ -147,12 +148,11 @@ class SalarySlip(TransactionBase):
'tax_on_additional_salary': additional_tax
})
else:
if overwrite:
component_row.default_amount = amount
component_row.amount = amount
else:
component_row.default_amount += amount
component_row.amount = component_row.default_amount
if not overwrite:
amount += struct_row.get("default_amount", 0)
component_row.default_amount = amount
component_row.amount = amount
component_row.tax_on_flexible_benefit = benefit_tax
component_row.tax_on_additional_salary = additional_tax
@@ -167,7 +167,7 @@ class SalarySlip(TransactionBase):
if d.amount_based_on_formula:
formula = d.formula.strip() if d.formula else None
if formula:
amount = frappe.safe_eval(formula, self.whitelisted_globals, data)
amount = rounded(frappe.safe_eval(formula, self.whitelisted_globals, data))
if amount:
data[d.abbr] = amount
@@ -418,7 +418,7 @@ class SalarySlip(TransactionBase):
for d in self.get(component_type):
if (self.salary_structure and
cint(d.depends_on_lwp) and
cint(d.depends_on_payment_days) and
(not
self.salary_slip_based_on_timesheet or
getdate(self.start_date) < joining_date or
@@ -431,7 +431,7 @@ class SalarySlip(TransactionBase):
)
elif not self.payment_days and not self.salary_slip_based_on_timesheet and \
cint(d.depends_on_lwp):
cint(d.depends_on_payment_days):
d.amount = 0
elif not d.amount:
d.amount = d.default_amount
@@ -441,7 +441,7 @@ class SalarySlip(TransactionBase):
def calculate_net_pay(self):
if self.salary_structure:
self.calculate_component_amounts()
disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total"))
precision = frappe.defaults.get_global_default("currency_precision")
self.total_deduction = 0
@@ -455,7 +455,7 @@ 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,
self.precision("net_pay") if disable_rounded_total else 0)
if self.net_pay < 0:
frappe.throw(_("Net Pay cannnot be negative"))
@@ -599,12 +599,11 @@ class SalarySlip(TransactionBase):
annual_earning = taxable_earning["taxable_earning"] * period_factor
exemption_amount = 0
if frappe.db.exists("Employee Tax Exemption Declaration", {"employee": self.employee,
"payroll_period": payroll_period.name, "docstatus": 1}):
"payroll_period": payroll_period.name, "docstatus": 1}):
exemption_amount = frappe.db.get_value("Employee Tax Exemption Declaration",
{"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1},
"total_exemption_amount")
annual_taxable_earning = annual_earning - exemption_amount
if self.deduct_tax_for_unclaimed_employee_benefits or self.deduct_tax_for_unsubmitted_tax_exemption_proof:
tax_detail = self.get_tax_paid_in_period(payroll_period, tax_component)
if tax_detail:
@@ -736,22 +735,24 @@ class SalarySlip(TransactionBase):
# less paid taxes
if args.get("pro_rata_tax_paid"):
tax_amount -= args.get("pro_rata_tax_paid")
tax_amount = rounded(tax_amount)
struct_row = self.get_salary_slip_row(args.get("tax_component"))
return [struct_row, tax_amount, benefit_tax, additional_tax]
def calculate_tax_by_tax_slab(self, payroll_period, annual_earning):
def calculate_tax_by_tax_slab(self, payroll_period, annual_taxable_earning):
payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period)
data = self.get_data_for_eval()
data.update({"annual_taxable_earning": annual_taxable_earning})
taxable_amount = 0
for slab in payroll_period_obj.taxable_salary_slabs:
if slab.condition and not self.eval_tax_slab_condition(slab.condition, data):
continue
if not slab.to_amount and annual_earning > slab.from_amount:
taxable_amount += (annual_earning - slab.from_amount) * slab.percent_deduction *.01
if not slab.to_amount and annual_taxable_earning > slab.from_amount:
taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
continue
if annual_earning > slab.from_amount and annual_earning < slab.to_amount:
taxable_amount += (annual_earning - slab.from_amount) * slab.percent_deduction *.01
elif annual_earning > slab.from_amount and annual_earning > slab.to_amount:
if annual_taxable_earning > slab.from_amount and annual_taxable_earning < slab.to_amount:
taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01
elif annual_taxable_earning > slab.from_amount and annual_taxable_earning > slab.to_amount:
taxable_amount += (slab.to_amount - slab.from_amount) * slab.percent_deduction * .01
return taxable_amount
@@ -770,13 +771,21 @@ class SalarySlip(TransactionBase):
def get_period_factor(self, period_start, period_end, start_date=None, end_date=None):
# TODO if both deduct checked update the factor to make tax consistent
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee, ["date_of_joining", "relieving_date"])
if getdate(joining_date) > getdate(period_start):
period_start = joining_date
if relieving_date and getdate(relieving_date) < getdate(period_end):
period_end = relieving_date
payroll_days = date_diff(period_end, period_start) + 1
if start_date and end_date:
salary_days = date_diff(end_date, start_date) + 1
return flt(payroll_days)/flt(salary_days)
# if period configured for a year and monthly frequency return 12 to make tax calc consistent
if 360 <= payroll_days <= 370 and self.payroll_frequency == "Monthly":
return 12
salary_days = date_diff(self.end_date, self.start_date) + 1
return flt(payroll_days)/flt(salary_days)
@@ -784,7 +793,7 @@ class SalarySlip(TransactionBase):
component = frappe.get_doc("Salary Component", salary_component)
# Data for update_component_row
struct_row = {}
struct_row['depends_on_lwp'] = component.depends_on_lwp
struct_row['depends_on_payment_days'] = component.depends_on_payment_days
struct_row['salary_component'] = component.name
struct_row['abbr'] = component.salary_component_abbr
struct_row['do_not_include_in_total'] = component.do_not_include_in_total

View File

@@ -246,7 +246,7 @@ frappe.ui.form.on('Salary Detail', {
frappe.model.set_value(cdt, cdn, 'amount', result.amount);
}
frappe.model.set_value(cdt, cdn, 'statistical_component', result.statistical_component);
frappe.model.set_value(cdt, cdn, 'depends_on_lwp', result.depends_on_lwp);
frappe.model.set_value(cdt, cdn, 'depends_on_payment_days', result.depends_on_payment_days);
frappe.model.set_value(cdt, cdn, 'do_not_include_in_total', result.do_not_include_in_total);
frappe.model.set_value(cdt, cdn, 'variable_based_on_taxable_salary', result.variable_based_on_taxable_salary);
frappe.model.set_value(cdt, cdn, 'is_tax_applicable', result.is_tax_applicable);

View File

@@ -18,7 +18,7 @@ class SalaryStructure(Document):
self.validate_max_benefits_with_flexi()
def set_missing_values(self):
overwritten_fields = ["depends_on_lwp", "variable_based_on_taxable_salary", "is_tax_applicable", "is_flexible_benefit"]
overwritten_fields = ["depends_on_payment_days", "variable_based_on_taxable_salary", "is_tax_applicable", "is_flexible_benefit"]
overwritten_fields_if_missing = ["amount_based_on_formula", "formula", "amount"]
for table in ["earnings", "deductions"]:
for d in self.get(table):
@@ -126,7 +126,7 @@ def create_salary_structures_assignment(employee, salary_structure, from_date, b
def get_existing_assignments(employees, salary_structure,from_date):
salary_structures_assignments = frappe.db.sql_list("""
select distinct employee from `tabSalary Structure Assignment`
select distinct employee from `tabSalary Structure Assignment`
where salary_structure=%s and employee in (%s)
and from_date=%s and docstatus=1
""" % ('%s', ', '.join(['%s']*len(employees)),'%s'), [salary_structure] + employees+[from_date])

View File

@@ -1,18 +1,18 @@
{
"creation": "2016-07-07 12:38:32.447281",
"custom_format": 0,
"disabled": 0,
"doc_type": "Salary Slip",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"HTML\", \"options\": \" <h3 style=\\\"text-align: right;\\\">{{doc.name}}</h3><div><hr></div> \"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"employee\"}, {\"print_hide\": 0, \"fieldname\": \"employee_name\"}, {\"print_hide\": 0, \"fieldname\": \"department\"}, {\"print_hide\": 0, \"fieldname\": \"designation\"}, {\"print_hide\": 0, \"fieldname\": \"branch\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"start_date\"}, {\"print_hide\": 0, \"fieldname\": \"end_date\"}, {\"print_hide\": 0, \"fieldname\": \"total_working_hours\"}, {\"print_hide\": 0, \"fieldname\": \"hour_rate\"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"time_sheet\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"working_hours\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"timesheets\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"depends_on_lwp\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"earnings\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"depends_on_lwp\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"deductions\"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"gross_pay\"}, {\"print_hide\": 0, \"fieldname\": \"total_deduction\"}, {\"print_hide\": 0, \"fieldname\": \"net_pay\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\"}, {\"print_hide\": 0, \"fieldname\": \"total_in_words\"}]",
"idx": 0,
"modified": "2016-08-21 21:02:59.896033",
"modified_by": "Administrator",
"name": "Salary Slip based on Timesheet",
"owner": "Administrator",
"print_format_builder": 1,
"print_format_type": "Server",
"creation": "2016-07-07 12:38:32.447281",
"custom_format": 0,
"disabled": 0,
"doc_type": "Salary Slip",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"HTML\", \"options\": \" <h3 style=\\\"text-align: right;\\\">{{doc.name}}</h3><div><hr></div> \"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"employee\"}, {\"print_hide\": 0, \"fieldname\": \"employee_name\"}, {\"print_hide\": 0, \"fieldname\": \"department\"}, {\"print_hide\": 0, \"fieldname\": \"designation\"}, {\"print_hide\": 0, \"fieldname\": \"branch\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"start_date\"}, {\"print_hide\": 0, \"fieldname\": \"end_date\"}, {\"print_hide\": 0, \"fieldname\": \"total_working_hours\"}, {\"print_hide\": 0, \"fieldname\": \"hour_rate\"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"time_sheet\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"working_hours\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"timesheets\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"depends_on_payment_days\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"earnings\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"depends_on_payment_days\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"deductions\"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"gross_pay\"}, {\"print_hide\": 0, \"fieldname\": \"total_deduction\"}, {\"print_hide\": 0, \"fieldname\": \"net_pay\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\"}, {\"print_hide\": 0, \"fieldname\": \"total_in_words\"}]",
"idx": 0,
"modified": "2016-08-21 21:02:59.896033",
"modified_by": "Administrator",
"name": "Salary Slip based on Timesheet",
"owner": "Administrator",
"print_format_builder": 1,
"print_format_type": "Server",
"standard": "Yes"
}

View File

@@ -1,22 +1,22 @@
{
"align_labels_right": 0,
"creation": "2016-07-07 11:45:14.872204",
"custom_format": 0,
"disabled": 0,
"doc_type": "Salary Slip",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \" <h3 style=\\\"text-align: right;\\\"><span style=\\\"line-height: 1.42857;\\\">{{doc.name}}</span></h3>\\n<div>\\n <hr style=\\\"text-align: center;\\\">\\n</div> \"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"employee\", \"label\": \"Employee\"}, {\"print_hide\": 0, \"fieldname\": \"company\", \"label\": \"Company\"}, {\"print_hide\": 0, \"fieldname\": \"employee_name\", \"label\": \"Employee Name\"}, {\"print_hide\": 0, \"fieldname\": \"department\", \"label\": \"Department\"}, {\"print_hide\": 0, \"fieldname\": \"designation\", \"label\": \"Designation\"}, {\"print_hide\": 0, \"fieldname\": \"branch\", \"label\": \"Branch\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"start_date\", \"label\": \"Start Date\"}, {\"print_hide\": 0, \"fieldname\": \"end_date\", \"label\": \"End Date\"}, {\"print_hide\": 0, \"fieldname\": \"total_working_days\", \"label\": \"Working Days\"}, {\"print_hide\": 0, \"fieldname\": \"leave_without_pay\", \"label\": \"Leave Without Pay\"}, {\"print_hide\": 0, \"fieldname\": \"payment_days\", \"label\": \"Payment Days\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"earnings\", \"label\": \"Earnings\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"depends_on_lwp\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"deductions\", \"label\": \"Deductions\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"gross_pay\", \"label\": \"Gross Pay\"}, {\"print_hide\": 0, \"fieldname\": \"total_deduction\", \"label\": \"Total Deduction\"}, {\"print_hide\": 0, \"fieldname\": \"net_pay\", \"label\": \"Net Pay\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\", \"label\": \"Rounded Total\"}, {\"print_hide\": 0, \"fieldname\": \"total_in_words\", \"label\": \"Total in words\"}]",
"idx": 0,
"line_breaks": 0,
"modified": "2018-07-24 19:31:39.040701",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Slip Standard",
"owner": "Administrator",
"print_format_builder": 1,
"print_format_type": "Server",
"show_section_headings": 0,
"align_labels_right": 0,
"creation": "2016-07-07 11:45:14.872204",
"custom_format": 0,
"disabled": 0,
"doc_type": "Salary Slip",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \" <h3 style=\\\"text-align: right;\\\"><span style=\\\"line-height: 1.42857;\\\">{{doc.name}}</span></h3>\\n<div>\\n <hr style=\\\"text-align: center;\\\">\\n</div> \"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"employee\", \"label\": \"Employee\"}, {\"print_hide\": 0, \"fieldname\": \"company\", \"label\": \"Company\"}, {\"print_hide\": 0, \"fieldname\": \"employee_name\", \"label\": \"Employee Name\"}, {\"print_hide\": 0, \"fieldname\": \"department\", \"label\": \"Department\"}, {\"print_hide\": 0, \"fieldname\": \"designation\", \"label\": \"Designation\"}, {\"print_hide\": 0, \"fieldname\": \"branch\", \"label\": \"Branch\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"start_date\", \"label\": \"Start Date\"}, {\"print_hide\": 0, \"fieldname\": \"end_date\", \"label\": \"End Date\"}, {\"print_hide\": 0, \"fieldname\": \"total_working_days\", \"label\": \"Working Days\"}, {\"print_hide\": 0, \"fieldname\": \"leave_without_pay\", \"label\": \"Leave Without Pay\"}, {\"print_hide\": 0, \"fieldname\": \"payment_days\", \"label\": \"Payment Days\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"earnings\", \"label\": \"Earnings\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"depends_on_payment_days\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"deductions\", \"label\": \"Deductions\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"gross_pay\", \"label\": \"Gross Pay\"}, {\"print_hide\": 0, \"fieldname\": \"total_deduction\", \"label\": \"Total Deduction\"}, {\"print_hide\": 0, \"fieldname\": \"net_pay\", \"label\": \"Net Pay\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\", \"label\": \"Rounded Total\"}, {\"print_hide\": 0, \"fieldname\": \"total_in_words\", \"label\": \"Total in words\"}]",
"idx": 0,
"line_breaks": 0,
"modified": "2018-07-24 19:31:39.040701",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Slip Standard",
"owner": "Administrator",
"print_format_builder": 1,
"print_format_type": "Server",
"show_section_headings": 0,
"standard": "Yes"
}

View File

@@ -201,7 +201,7 @@ class BOM(WebsiteGenerator):
if not rate:
if self.rm_cost_as_per == "Price List":
frappe.msgprint(_("Price not found for item {0} and price list {1}")
frappe.msgprint(_("Price not found for item {0} in price list {1}")
.format(arg["item_code"], self.buying_price_list), alert=True)
else:
frappe.msgprint(_("{0} not found for item {1}")

View File

@@ -592,3 +592,6 @@ erpnext.patches.v11_1.make_job_card_time_logs
erpnext.patches.v11_1.set_variant_based_on
erpnext.patches.v11_1.move_customer_lead_to_dynamic_column
erpnext.patches.v11_1.woocommerce_set_creation_user
erpnext.patches.v11_1.delete_bom_browser
erpnext.patches.v11_1.set_salary_details_submittable
erpnext.patches.v11_1.rename_depends_on_lwp

View File

@@ -0,0 +1,8 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.delete_doc_if_exists('Page', 'bom-browser')

View File

@@ -0,0 +1,13 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe import scrub
from frappe.model.utils.rename_field import rename_field
def execute():
for doctype in ("Salary Component", "Salary Detail"):
if "depends_on_lwp" in frappe.db.get_table_columns(doctype):
frappe.reload_doc("hr", "doctype", scrub(doctype))
rename_field(doctype, "depends_on_lwp", "depends_on_payment_days")

View File

@@ -0,0 +1,9 @@
from __future__ import unicode_literals
import frappe
def execute():
frappe.db.sql("""
update `tabSalary Structure` ss, `tabSalary Detail` sd
set sd.docstatus=1
where ss.name=sd.parent and ss.docstatus=1 and sd.parenttype='Salary Structure'
""")

View File

@@ -1,10 +1,11 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cint
def execute():
woocommerce_setting_enable_sync = frappe.db.sql("SELECT t.value FROM tabSingles t WHERE doctype = 'Woocommerce Settings' AND field = 'enable_sync'", as_dict=True)
if len(woocommerce_setting_enable_sync) and woocommerce_setting_enable_sync[0].value == '1':
frappe.db.sql("""UPDATE tabSingles
SET value = (SELECT t.value FROM tabSingles t WHERE doctype = 'Woocommerce Settings' AND field = 'modified_by')
WHERE doctype = 'Woocommerce Settings'
AND field = 'creation_user';""")
frappe.reload_doc("erpnext_integrations", "doctype","woocommerce_settings")
doc = frappe.get_doc("Woocommerce Settings")
if cint(doc.enable_sync):
doc.creation_user = doc.modified_by
doc.save(ignore_permissions=True)

View File

@@ -5,79 +5,79 @@ from frappe.model.utils.rename_field import update_property_setters
def execute():
if not frappe.db.exists("DocType", "Salary Structure Earning"):
return
frappe.reload_doc("hr", "doctype", "salary_detail")
frappe.reload_doc("hr", "doctype", "salary_component")
standard_cols = ["name", "creation", "modified", "owner", "modified_by", "parent", "parenttype", "parentfield", "idx"]
dt_cols = {
"Salary Structure Deduction": ["d_type", "d_modified_amt", "depend_on_lwp"],
"Salary Structure Earning": ["e_type", "modified_value", "depend_on_lwp"],
"Salary Slip Earning": ["e_type", "e_modified_amount", "e_depends_on_lwp", "e_amount"],
"Salary Slip Deduction": ["d_type", "d_modified_amount", "d_depends_on_lwp", "d_amount"],
}
earning_type_exists = True if "earning_type" in frappe.db.get_table_columns("Salary Slip Earning") else False
e_type_exists = True if "e_type" in frappe.db.get_table_columns("Salary Slip Earning") else False
if e_type_exists and earning_type_exists:
frappe.db.sql("""update `tabSalary Slip Earning`
frappe.db.sql("""update `tabSalary Slip Earning`
set e_type = earning_type, e_modified_amount = earning_amount
where e_type is null and earning_type is not null""")
frappe.db.sql("""update `tabSalary Structure Earning` set e_type = earning_type
frappe.db.sql("""update `tabSalary Structure Earning` set e_type = earning_type
where e_type is null and earning_type is not null""")
frappe.db.sql("""update `tabSalary Slip Deduction` set
frappe.db.sql("""update `tabSalary Slip Deduction` set
d_type = deduction_type, d_modified_amount = deduction_amount
where d_type is null and deduction_type is not null""")
frappe.db.sql("""update `tabSalary Structure Deduction` set d_type = deduction_type
frappe.db.sql("""update `tabSalary Structure Deduction` set d_type = deduction_type
where d_type is null and deduction_type is not null""")
if earning_type_exists and not e_type_exists:
for val in dt_cols.values():
if val[0] == "e_type":
val[0] = "earning_type"
if val[0] == "d_type":
val[0] = "deduction_type"
if val[1] == "e_modified_amount":
val[1] ="earning_amount"
if val[1] == "d_modified_amount":
val[1] ="deduction_amount"
target_cols = standard_cols + ["salary_component", "amount", "depends_on_lwp", "default_amount"]
target_cols = "`" + "`, `".join(target_cols) + "`"
for doctype, cols in dt_cols.items():
target_cols = standard_cols + ["salary_component", "amount", "depends_on_payment_days", "default_amount"]
target_cols = "`" + "`, `".join(target_cols) + "`"
for doctype, cols in dt_cols.items():
source_cols = "`" + "`, `".join(standard_cols + cols) + "`"
if len(cols) == 3:
source_cols += ", 0"
frappe.db.sql("""INSERT INTO `tabSalary Detail` ({0}) SELECT {1} FROM `tab{2}`"""
.format(target_cols, source_cols, doctype))
dt_cols_de = {
"Deduction Type": ["deduction_name", "description"],
"Earning Type": ["earning_name", "description"],
}
standard_cols_de = standard_cols
target_cols = standard_cols_de + ["salary_component", "description"]
target_cols = "`" + "`, `".join(target_cols) + "`"
for doctype, cols in dt_cols_de.items():
target_cols = "`" + "`, `".join(target_cols) + "`"
for doctype, cols in dt_cols_de.items():
source_cols = "`" + "`, `".join(standard_cols_de + cols) + "`"
try:
frappe.db.sql("""INSERT INTO `tabSalary Component` ({0}) SELECT {1} FROM `tab{2}`"""
@@ -85,10 +85,10 @@ def execute():
except Exception as e:
if e.args[0]==1062:
pass
update_customizations()
for doctype in ["Salary Structure Deduction", "Salary Structure Earning", "Salary Slip Earning",
for doctype in ["Salary Structure Deduction", "Salary Structure Earning", "Salary Slip Earning",
"Salary Slip Deduction", "Deduction Type", "Earning Type"] :
frappe.delete_doc("DocType", doctype)
@@ -96,35 +96,35 @@ def execute():
def update_customizations():
dt_cols = {
"Salary Structure Deduction": {
"d_type": "salary_component",
"deduction_type": "salary_component",
"d_type": "salary_component",
"deduction_type": "salary_component",
"d_modified_amt": "amount",
"depend_on_lwp": "depends_on_lwp"
"depend_on_lwp": "depends_on_payment_days"
},
"Salary Structure Earning": {
"e_type": "salary_component",
"earning_type": "salary_component",
"e_type": "salary_component",
"earning_type": "salary_component",
"modified_value": "amount",
"depend_on_lwp": "depends_on_lwp"
"depend_on_lwp": "depends_on_payment_days"
},
"Salary Slip Earning": {
"e_type": "salary_component",
"earning_type": "salary_component",
"e_type": "salary_component",
"earning_type": "salary_component",
"e_modified_amount": "amount",
"e_amount" : "default_amount",
"e_depends_on_lwp": "depends_on_lwp"
"e_depends_on_lwp": "depends_on_payment_days"
},
"Salary Slip Deduction": {
"d_type": "salary_component",
"deduction_type": "salary_component",
"d_type": "salary_component",
"deduction_type": "salary_component",
"d_modified_amount": "amount",
"d_amount" : "default_amount",
"d_depends_on_lwp": "depends_on_lwp"
"d_depends_on_lwp": "depends_on_payment_days"
}
}
update_property_setters_and_custom_fields("Salary Detail", dt_cols)
dt_cols = {
"Earning Type": {
"earning_name": "salary_component"
@@ -133,17 +133,17 @@ def update_customizations():
"deduction_name": "salary_component"
}
}
update_property_setters_and_custom_fields("Salary Component", dt_cols)
def update_property_setters_and_custom_fields(new_dt, dt_cols):
for doctype, cols in dt_cols.items():
frappe.db.sql("update `tabProperty Setter` set doc_type = %s where doc_type=%s", (new_dt, doctype))
frappe.db.sql("update `tabCustom Field` set dt = %s where dt=%s", (new_dt, doctype))
for old_fieldname, new_fieldname in cols.items():
update_property_setters(new_dt, old_fieldname, new_fieldname)

View File

@@ -241,7 +241,7 @@ class Project(Document):
from_expense_claim = frappe.db.sql("""select
sum(total_sanctioned_amount) as total_sanctioned_amount
from `tabExpense Claim` where project = %s
and docstatus = 1""", self.name, as_dict=1, debug=1)[0]
and docstatus = 1""", self.name, as_dict=1)[0]
self.actual_start_date = from_time_sheet.start_date
self.actual_end_date = from_time_sheet.end_date

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
@@ -19,6 +20,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "subject",
"fieldtype": "Data",
"hidden": 0,
@@ -51,6 +53,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "project",
"fieldtype": "Link",
"hidden": 0,
@@ -86,6 +89,7 @@
"collapsible": 0,
"columns": 0,
"default": "0",
"fetch_if_empty": 0,
"fieldname": "is_group",
"fieldtype": "Check",
"hidden": 0,
@@ -118,6 +122,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break0",
"fieldtype": "Column Break",
"hidden": 0,
@@ -151,6 +156,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
@@ -185,6 +191,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "priority",
"fieldtype": "Select",
"hidden": 0,
@@ -219,6 +226,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "parent_task",
"fieldtype": "Link",
"hidden": 0,
@@ -254,6 +262,7 @@
"collapsible_depends_on": "",
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "section_break_10",
"fieldtype": "Section Break",
"hidden": 0,
@@ -286,6 +295,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "exp_start_date",
"fieldtype": "Date",
"hidden": 0,
@@ -322,6 +332,7 @@
"default": "0",
"depends_on": "",
"description": "",
"fetch_if_empty": 0,
"fieldname": "expected_time",
"fieldtype": "Float",
"hidden": 0,
@@ -356,6 +367,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "task_weight",
"fieldtype": "Float",
"hidden": 0,
@@ -388,6 +400,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_11",
"fieldtype": "Column Break",
"hidden": 0,
@@ -420,6 +433,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "exp_end_date",
"fieldtype": "Date",
"hidden": 0,
@@ -454,6 +468,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "progress",
"fieldtype": "Percent",
"hidden": 0,
@@ -487,6 +502,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "is_milestone",
"fieldtype": "Check",
"hidden": 0,
@@ -519,6 +535,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "color",
"fieldtype": "Color",
"hidden": 0,
@@ -553,6 +570,7 @@
"collapsible_depends_on": "",
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "section_break0",
"fieldtype": "Section Break",
"hidden": 0,
@@ -586,6 +604,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "description",
"fieldtype": "Text Editor",
"hidden": 0,
@@ -623,6 +642,7 @@
"collapsible_depends_on": "",
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "section_break",
"fieldtype": "Section Break",
"hidden": 0,
@@ -656,6 +676,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "depends_on",
"fieldtype": "Table",
"hidden": 0,
@@ -690,6 +711,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "depends_on_tasks",
"fieldtype": "Data",
"hidden": 1,
@@ -725,6 +747,7 @@
"columns": 0,
"depends_on": "",
"description": "",
"fetch_if_empty": 0,
"fieldname": "actual",
"fieldtype": "Section Break",
"hidden": 0,
@@ -760,6 +783,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "act_start_date",
"fieldtype": "Date",
"hidden": 0,
@@ -796,6 +820,7 @@
"default": "",
"depends_on": "",
"description": "",
"fetch_if_empty": 0,
"fieldname": "actual_time",
"fieldtype": "Float",
"hidden": 0,
@@ -829,6 +854,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_15",
"fieldtype": "Column Break",
"hidden": 0,
@@ -861,6 +887,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "act_end_date",
"fieldtype": "Date",
"hidden": 0,
@@ -895,6 +922,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "section_break_17",
"fieldtype": "Section Break",
"hidden": 0,
@@ -927,6 +955,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "total_costing_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -962,6 +991,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "total_expense_claim",
"fieldtype": "Currency",
"hidden": 0,
@@ -995,6 +1025,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_20",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1027,6 +1058,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "total_billing_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -1059,6 +1091,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "more_details",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1091,6 +1124,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.status == \"Closed\" || doc.status == \"Pending Review\"",
"fetch_if_empty": 0,
"fieldname": "review_date",
"fieldtype": "Date",
"hidden": 0,
@@ -1125,6 +1159,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.status == \"Closed\"",
"fetch_if_empty": 0,
"fieldname": "closing_date",
"fieldtype": "Date",
"hidden": 0,
@@ -1158,6 +1193,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_22",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1188,6 +1224,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "department",
"fieldtype": "Link",
"hidden": 0,
@@ -1221,6 +1258,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -1253,6 +1291,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 1,
@@ -1285,6 +1324,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
@@ -1317,6 +1357,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "old_parent",
"fieldtype": "Data",
"hidden": 1,
@@ -1355,7 +1396,7 @@
"istable": 0,
"max_attachments": 5,
"menu_index": 0,
"modified": "2018-08-21 16:15:56.299895",
"modified": "2019-04-18 22:33:03.798331",
"modified_by": "Administrator",
"module": "Projects",
"name": "Task",
@@ -1385,7 +1426,7 @@
"read_only": 0,
"read_only_onload": 0,
"search_fields": "subject",
"show_name_in_global_search": 0,
"show_name_in_global_search": 1,
"sort_order": "DESC",
"timeline_field": "project",
"title_field": "subject",

View File

@@ -54,9 +54,6 @@ def get_data(filters):
data = []
record = get_records(filters)
billable_hours_worked = 0
hours_worked = 0
working_cost = 0
for entries in record:
total_hours = 0
total_billable_hours = 0
@@ -81,11 +78,6 @@ def get_data(filters):
total_hours, total_billable_hours, total_amount = get_billable_and_total_hours(activity,
time_end, time_start, total_hours, total_billable_hours, total_amount)
hours_worked += total_hours
billable_hours_worked += total_billable_hours
working_cost += total_amount
row = {
"employee": entries.employee,
"employee_name": entries.employee_name,
@@ -97,14 +89,6 @@ def get_data(filters):
if entries_exists:
data.append(row)
entries_exists = False
total = {
"total_billable_hours": billable_hours_worked,
"total_hours": hours_worked,
"amount": working_cost
}
if billable_hours_worked !=0 or hours_worked !=0 or working_cost !=0:
data.append(total)
return data
def get_records(filters):

View File

@@ -1,5 +1,5 @@
{
"add_total_row": 0,
"add_total_row": 1,
"creation": "2019-03-08 15:08:19.929728",
"disable_prepared_report": 0,
"disabled": 0,
@@ -7,7 +7,7 @@
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2019-03-08 15:08:19.929728",
"modified": "2019-04-16 17:29:18.376932",
"modified_by": "Administrator",
"module": "Projects",
"name": "Employee Billing Summary",

View File

@@ -1,5 +1,5 @@
{
"add_total_row": 0,
"add_total_row": 1,
"creation": "2019-03-11 16:22:39.460524",
"disable_prepared_report": 0,
"disabled": 0,
@@ -7,7 +7,7 @@
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2019-03-11 16:22:39.460524",
"modified": "2019-04-16 17:28:32.749633",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project Billing Summary",

View File

@@ -33,7 +33,7 @@ frappe.ui.form.on("Communication", {
make_lead_from_communication: (frm) => {
return frappe.call({
method: "frappe.email.inbox.make_lead_from_communication",
method: "erpnext.crm.doctype.lead.lead.make_lead_from_communication",
args: {
communication: frm.doc.name
},
@@ -48,7 +48,7 @@ frappe.ui.form.on("Communication", {
make_issue_from_communication: (frm) => {
return frappe.call({
method: "frappe.email.inbox.make_issue_from_communication",
method: "erpnext.support.doctype.issue.issue.make_issue_from_communication",
args: {
communication: frm.doc.name
},
@@ -63,7 +63,7 @@ frappe.ui.form.on("Communication", {
make_opportunity_from_communication: (frm) => {
return frappe.call({
method: "frappe.email.inbox.make_opportunity_from_communication",
method: "erpnext.crm.doctype.opportunity.opportunity.make_opportunity_from_communication",
args: {
communication: frm.doc.name
},

View File

@@ -290,7 +290,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
args: { search_value: this.frm.doc.scan_barcode }
}).then(r => {
const data = r && r.message;
if (!data) {
if (!data || Object.keys(data).length === 0) {
scan_barcode_field.set_new_description(__('Cannot find Item with this barcode'));
return;
}

View File

@@ -38,7 +38,6 @@ class Gstr1Report(object):
shipping_bill_date,
reason_for_issuing_document
"""
self.customer_type = "Company" if self.filters.get("type_of_business") == "B2B" else "Individual"
def run(self):
self.get_columns()
@@ -54,18 +53,50 @@ class Gstr1Report(object):
return self.columns, self.data
def get_data(self):
if self.filters.get("type_of_business") == "B2C Small":
self.get_b2cs_data()
else:
for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
invoice_details = self.invoices.get(inv)
for rate, items in items_based_on_rate.items():
row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items)
if self.filters.get("type_of_business") == "CDNR":
row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N")
row.append("C" if invoice_details.return_against else "R")
self.data.append(row)
def get_b2cs_data(self):
b2cs_output = {}
for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
invoice_details = self.invoices.get(inv)
for rate, items in items_based_on_rate.items():
row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items)
if self.filters.get("type_of_business") == "B2C Small":
row.append("E" if invoice_details.ecommerce_gstin else "OE")
place_of_supply = invoice_details.get("place_of_supply")
ecommerce_gstin = invoice_details.get("ecommerce_gstin")
if self.filters.get("type_of_business") == "CDNR":
row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N")
row.append("C" if invoice_details.return_against else "R")
b2cs_output.setdefault((rate, place_of_supply, ecommerce_gstin),{
"place_of_supply": "",
"ecommerce_gstin": "",
"rate": "",
"taxable_value": 0,
"cess_amount": 0,
"type": 0
})
self.data.append(row)
row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin))
row["place_of_supply"] = place_of_supply
row["ecommerce_gstin"] = ecommerce_gstin
row["rate"] = rate
row["taxable_value"] += sum([abs(net_amount)
for item_code, net_amount in self.invoice_items.get(inv).items() if item_code in items])
row["type"] = "E" if ecommerce_gstin else "OE"
for key, value in iteritems(b2cs_output):
self.data.append(value)
def get_row_data_for_invoice(self, invoice, invoice_details, tax_rate, items):
row = []
@@ -113,7 +144,7 @@ class Gstr1Report(object):
if self.filters.get(opts[0]):
conditions += opts[1]
customers = frappe.get_all("Customer", filters={"customer_type": self.customer_type})
customers = frappe.get_all("Customer", filters={"disabled": 0})
if self.filters.get("type_of_business") == "B2B":
conditions += """ and ifnull(invoice_type, '') != 'Export' and is_return != 1

View File

@@ -123,5 +123,11 @@ frappe.ui.form.on("Customer", {
},
validate: function(frm) {
if(frm.doc.lead_name) frappe.model.clear_doc("Lead", frm.doc.lead_name);
var total = 0;
for (var idx in frm.doc.sales_team) {
total += frm.doc.sales_team[idx].allocated_percentage;
if (total > 100) frappe.throw(__("Total contribution percentage can't exceed 100"));
}
},
});

View File

@@ -12,7 +12,7 @@ def execute(filters=None):
iwq_map = get_item_warehouse_quantity_map()
item_map = get_item_details()
data = []
data = []
for sbom, warehouse in iwq_map.items():
total = 0
total_qty = 0
@@ -21,7 +21,7 @@ def execute(filters=None):
total += 1
row = [sbom, item_map.get(sbom).item_name, item_map.get(sbom).description,
item_map.get(sbom).stock_uom, wh]
available_qty = min(item_qty.values())
available_qty = item_qty
total_qty += flt(available_qty)
row += [available_qty]
@@ -66,15 +66,30 @@ def get_item_warehouse_quantity():
return iwq_map
def get_item_warehouse_quantity_map():
query = """SELECT parent, warehouse, MIN(qty) AS qty
FROM (SELECT b.parent, bi.item_code, bi.warehouse,
sum(bi.projected_qty) / b.qty AS qty
FROM tabBin AS bi, (SELECT b.parent, b.item_code, b.qty, w.name
FROM `tabProduct Bundle Item` b, `tabWarehouse` w) AS b
WHERE bi.item_code = b.item_code
AND bi.warehouse = b.name
GROUP BY b.parent, b.item_code, bi.warehouse
UNION ALL
SELECT b.parent, b.item_code, b.name, 0 AS qty
FROM (SELECT b.parent, b.item_code, b.qty, w.name
FROM `tabProduct Bundle Item` b, `tabWarehouse` w) AS b
WHERE NOT EXISTS(SELECT *
FROM `tabBin` AS bi
WHERE bi.item_code = b.item_code
AND bi.warehouse = b.name)) AS r
GROUP BY parent, warehouse
HAVING MIN(qty) != 0"""
result = frappe.db.sql(query, as_dict=1)
last_sbom = ""
sbom_map = {}
iwq_map = get_item_warehouse_quantity()
sbom_item_map = get_product_bundle_items()
for sbom, sbom_items in sbom_item_map.items():
for item, child_qty in sbom_items.items():
for wh, qty in iwq_map.get(item, {}).items():
avail_qty = flt(qty) / flt(child_qty)
sbom_map.setdefault(sbom, {}).setdefault(wh, {}) \
.setdefault(item, avail_qty)
return sbom_map
for line in result:
if line.get("parent") != last_sbom:
last_sbom = line.get("parent")
actual_dict = sbom_map.setdefault(last_sbom, {})
actual_dict.setdefault(line.get("warehouse"), line.get("qty"))
return sbom_map

View File

@@ -4,6 +4,8 @@ from __future__ import unicode_literals
import frappe
import unittest
import json
from frappe import _
from frappe.utils import random_string
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import get_charts_for_country
@@ -78,7 +80,10 @@ class TestCompany(unittest.TestCase):
if account_type in ["Bank", "Cash"]:
filters["is_group"] = 1
self.assertTrue(frappe.get_all("Account", filters))
has_matching_accounts = frappe.get_all("Account", filters)
error_message = _("No Account matched these filters: {}".format(json.dumps(filters)))
self.assertTrue(has_matching_accounts, msg=error_message)
finally:
self.delete_mode_of_payment(template)
frappe.delete_doc("Company", template)

View File

@@ -101,8 +101,7 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend(
refresh: function(doc, dt, dn) {
var me = this;
this._super();
if ((!doc.is_return) && (doc.status!="Closed" || doc.is_new())) {
if ((!doc.is_return) && (doc.status!="Closed" || this.frm.is_new())) {
if (this.frm.doc.docstatus===0) {
this.frm.add_custom_button(__('Sales Order'),
function() {

View File

@@ -407,7 +407,6 @@ def get_returned_qty_map(delivery_note):
@frappe.whitelist()
def make_sales_invoice(source_name, target_doc=None):
doc = frappe.get_doc('Delivery Note', source_name)
sales_orders = [d.against_sales_order for d in doc.items]
returned_qty_map = get_returned_qty_map(source_name)
invoiced_qty_map = get_invoiced_qty_map(source_name)
@@ -447,7 +446,7 @@ def make_sales_invoice(source_name, target_doc=None):
returned_qty = 0
return pending_qty, returned_qty
doc = get_mapped_doc("Delivery Note", source_name, {
doc = get_mapped_doc("Delivery Note", source_name, {
"Delivery Note": {
"doctype": "Sales Invoice",
"validation": {
@@ -465,7 +464,7 @@ def make_sales_invoice(source_name, target_doc=None):
"cost_center": "cost_center"
},
"postprocess": update_item,
"filter": lambda d: get_pending_qty(d)[0]<=0
"filter": lambda d: get_pending_qty(d)[0] <= 0 if not doc.get("is_return") else get_pending_qty(d)[0] > 0
},
"Sales Taxes and Charges": {
"doctype": "Sales Taxes and Charges",

View File

@@ -458,7 +458,7 @@ def make_purchase_invoice(source_name, target_doc=None):
"asset": "asset",
},
"postprocess": update_item,
"filter": lambda d: get_pending_qty(d)[0]<=0
"filter": lambda d: get_pending_qty(d)[0] <= 0 if not doc.get("is_return") else get_pending_qty(d)[0] > 0
},
"Purchase Taxes and Charges": {
"doctype": "Purchase Taxes and Charges",

View File

@@ -151,10 +151,10 @@ def get_opening_balance(filters, columns):
"posting_date": filters.from_date,
"posting_time": "00:00:00"
})
row = [""]*len(columns)
row[1] = _("'Opening'")
for i, v in ((9, 'qty_after_transaction'), (11, 'valuation_rate'), (12, 'stock_value')):
row[i] = last_entry.get(v, 0)
row = {}
row["item_code"] = _("'Opening'")
for dummy, v in ((9, 'qty_after_transaction'), (11, 'valuation_rate'), (12, 'stock_value')):
row[v] = last_entry.get(v, 0)
return row

View File

@@ -9,6 +9,7 @@ from frappe import _
from frappe.model.document import Document
from frappe.utils import now
from frappe.utils.user import is_website_user
from frappe.email.inbox import link_communication_to_document
sender_field = "raised_by"
@@ -160,3 +161,20 @@ def has_website_permission(doc, ptype, user, verbose=False):
def update_issue(contact, method):
"""Called when Contact is deleted"""
frappe.db.sql("""UPDATE `tabIssue` set contact='' where contact=%s""", contact.name)
@frappe.whitelist()
def make_issue_from_communication(communication, ignore_communication_links=False):
""" raise a issue from email """
doc = frappe.get_doc("Communication", communication)
issue = frappe.get_doc({
"doctype": "Issue",
"subject": doc.subject,
"communication_medium": doc.communication_medium,
"raised_by": doc.sender or "",
"raised_by_phone": doc.phone_no or ""
}).insert(ignore_permissions=True)
link_communication_to_document(doc, "Issue", issue.name, ignore_communication_links)
return issue.name

View File

@@ -5,50 +5,36 @@ from __future__ import unicode_literals
import frappe, erpnext
from frappe import _
from six import iteritems
def get_level():
activation_level = 0
sales_data = []
min_count = 0
doctypes = {"Item": 5, "Customer": 5, "Sales Order": 2, "Sales Invoice": 2, "Purchase Order": 2, "Employee": 3, "Lead": 3, "Quotation": 3,
"Payment Entry": 2, "User": 5, "Student": 5, "Instructor": 5, "BOM": 3, "Journal Entry": 3, "Stock Entry": 3}
for doctype, min_count in iteritems(doctypes):
count = frappe.db.count(doctype)
if count > min_count:
activation_level += 1
sales_data.append({doctype: count})
if frappe.db.get_single_value('System Settings', 'setup_complete'):
activation_level = 1
if frappe.db.count('Item') > 5:
activation_level += 1
if frappe.db.count('Customer') > 5:
activation_level += 1
if frappe.db.count('Sales Order') > 2:
activation_level += 1
if frappe.db.count('Purchase Order') > 2:
activation_level += 1
if frappe.db.count('Employee') > 3:
activation_level += 1
if frappe.db.count('Lead') > 3:
activation_level += 1
if frappe.db.count('Payment Entry') > 2:
activation_level += 1
if frappe.db.count('Communication', dict(communication_medium='Email')) > 10:
activation_level += 1
if frappe.db.count('User') > 5:
activation_level += 1
if frappe.db.count('Student') > 5:
activation_level += 1
if frappe.db.count('Instructor') > 5:
communication_number = frappe.db.count('Communication', dict(communication_medium='Email'))
if communication_number > 10:
activation_level += 1
sales_data.append({"Communication": communication_number})
# recent login
if frappe.db.sql('select name from tabUser where last_login > date_sub(now(), interval 2 day) limit 1'):
activation_level += 1
return activation_level
level = {"activation_level": activation_level, "sales_data": sales_data}
return level
def get_help_messages():
'''Returns help messages to be shown on Desktop'''