Merge branch 'hotfix'

This commit is contained in:
Sahil Khan
2019-04-22 14:05:43 +05:30
47 changed files with 1158 additions and 891 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

@@ -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,7 +41,7 @@ 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]})

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

@@ -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

@@ -83,7 +83,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 +207,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 +243,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
@@ -269,7 +275,7 @@ def check_amount_vs_description(amount_matching, description_matching):
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 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

@@ -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)

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",

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"
@@ -321,3 +322,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

@@ -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

@@ -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

@@ -590,4 +590,5 @@ erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v11_0.make_italian_localization_fields # 26-03-2019
erpnext.patches.v11_1.make_job_card_time_logs
erpnext.patches.v11_1.set_variant_based_on
erpnext.patches.v11_1.woocommerce_set_creation_user
erpnext.patches.v11_1.woocommerce_set_creation_user
erpnext.patches.v11_1.set_salary_details_submitable

View File

@@ -0,0 +1,11 @@
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

@@ -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

@@ -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'''