Merge branch 'develop' into skr04_equity_dev

This commit is contained in:
Raffael Meyer 2020-12-10 10:51:55 +01:00 committed by GitHub
commit 7f387452ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 144 additions and 80 deletions
erpnext
accounts/report
item_wise_purchase_register
item_wise_sales_register
assets/report/fixed_asset_register
crm/doctype
selling/report/item_wise_sales_history

@ -8,6 +8,7 @@ from frappe.utils import flt
from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import (get_tax_accounts, from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import (get_tax_accounts,
get_grand_total, add_total_row, get_display_value, get_group_by_and_display_fields, add_sub_total_row, get_grand_total, add_total_row, get_display_value, get_group_by_and_display_fields, add_sub_total_row,
get_group_by_conditions) get_group_by_conditions)
from erpnext.selling.report.item_wise_sales_history.item_wise_sales_history import get_item_details
def execute(filters=None): def execute(filters=None):
return _execute(filters) return _execute(filters)
@ -22,7 +23,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
aii_account_map = get_aii_accounts() aii_account_map = get_aii_accounts()
if item_list: if item_list:
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency, itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency,
doctype="Purchase Invoice", tax_doctype="Purchase Taxes and Charges") doctype='Purchase Invoice', tax_doctype='Purchase Taxes and Charges')
po_pr_map = get_purchase_receipts_against_purchase_order(item_list) po_pr_map = get_purchase_receipts_against_purchase_order(item_list)
@ -34,10 +35,14 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
if filters.get('group_by'): if filters.get('group_by'):
grand_total = get_grand_total(filters, 'Purchase Invoice') grand_total = get_grand_total(filters, 'Purchase Invoice')
item_details = get_item_details()
for d in item_list: for d in item_list:
if not d.stock_qty: if not d.stock_qty:
continue continue
item_record = item_details.get(d.item_code)
purchase_receipt = None purchase_receipt = None
if d.purchase_receipt: if d.purchase_receipt:
purchase_receipt = d.purchase_receipt purchase_receipt = d.purchase_receipt
@ -48,8 +53,8 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
row = { row = {
'item_code': d.item_code, 'item_code': d.item_code,
'item_name': d.item_name, 'item_name': item_record.item_name,
'item_group': d.item_group, 'item_group': item_record.item_group,
'description': d.description, 'description': d.description,
'invoice': d.parent, 'invoice': d.parent,
'posting_date': d.posting_date, 'posting_date': d.posting_date,
@ -81,10 +86,10 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
for tax in tax_columns: for tax in tax_columns:
item_tax = itemised_tax.get(d.name, {}).get(tax, {}) item_tax = itemised_tax.get(d.name, {}).get(tax, {})
row.update({ row.update({
frappe.scrub(tax + ' Rate'): item_tax.get("tax_rate", 0), frappe.scrub(tax + ' Rate'): item_tax.get('tax_rate', 0),
frappe.scrub(tax + ' Amount'): item_tax.get("tax_amount", 0), frappe.scrub(tax + ' Amount'): item_tax.get('tax_amount', 0),
}) })
total_tax += flt(item_tax.get("tax_amount")) total_tax += flt(item_tax.get('tax_amount'))
row.update({ row.update({
'total_tax': total_tax, 'total_tax': total_tax,
@ -309,8 +314,8 @@ def get_items(filters, additional_query_columns):
select select
`tabPurchase Invoice Item`.`name`, `tabPurchase Invoice Item`.`parent`, `tabPurchase Invoice Item`.`name`, `tabPurchase Invoice Item`.`parent`,
`tabPurchase Invoice`.posting_date, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.company, `tabPurchase Invoice`.posting_date, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.company,
`tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total, `tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total,
`tabPurchase Invoice Item`.`item_name`, `tabPurchase Invoice Item`.`item_group`, `tabPurchase Invoice Item`.description, `tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice Item`.description,
`tabPurchase Invoice Item`.`project`, `tabPurchase Invoice Item`.`purchase_order`, `tabPurchase Invoice Item`.`project`, `tabPurchase Invoice Item`.`purchase_order`,
`tabPurchase Invoice Item`.`purchase_receipt`, `tabPurchase Invoice Item`.`po_detail`, `tabPurchase Invoice Item`.`purchase_receipt`, `tabPurchase Invoice Item`.`po_detail`,
`tabPurchase Invoice Item`.`expense_account`, `tabPurchase Invoice Item`.`stock_qty`, `tabPurchase Invoice Item`.`expense_account`, `tabPurchase Invoice Item`.`stock_qty`,

@ -8,6 +8,7 @@ from frappe.utils import flt, cstr
from frappe.model.meta import get_field_precision from frappe.model.meta import get_field_precision
from frappe.utils.xlsxutils import handle_html from frappe.utils.xlsxutils import handle_html
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
from erpnext.selling.report.item_wise_sales_history.item_wise_sales_history import get_item_details, get_customer_details
def execute(filters=None): def execute(filters=None):
return _execute(filters) return _execute(filters)
@ -16,7 +17,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
if not filters: filters = {} if not filters: filters = {}
columns = get_columns(additional_table_columns, filters) columns = get_columns(additional_table_columns, filters)
company_currency = frappe.get_cached_value('Company', filters.get("company"), "default_currency") company_currency = frappe.get_cached_value('Company', filters.get('company'), 'default_currency')
item_list = get_items(filters, additional_query_columns) item_list = get_items(filters, additional_query_columns)
if item_list: if item_list:
@ -33,7 +34,13 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
if filters.get('group_by'): if filters.get('group_by'):
grand_total = get_grand_total(filters, 'Sales Invoice') grand_total = get_grand_total(filters, 'Sales Invoice')
customer_details = get_customer_details()
item_details = get_item_details()
for d in item_list: for d in item_list:
customer_record = customer_details.get(d.customer)
item_record = item_details.get(d.item_code)
delivery_note = None delivery_note = None
if d.delivery_note: if d.delivery_note:
delivery_note = d.delivery_note delivery_note = d.delivery_note
@ -45,14 +52,14 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
row = { row = {
'item_code': d.item_code, 'item_code': d.item_code,
'item_name': d.item_name, 'item_name': item_record.item_name,
'item_group': d.item_group, 'item_group': item_record.item_group,
'description': d.description, 'description': d.description,
'invoice': d.parent, 'invoice': d.parent,
'posting_date': d.posting_date, 'posting_date': d.posting_date,
'customer': d.customer, 'customer': d.customer,
'customer_name': d.customer_name, 'customer_name': customer_record.customer_name,
'customer_group': d.customer_group, 'customer_group': customer_record.customer_group,
} }
if additional_query_columns: if additional_query_columns:
@ -90,10 +97,10 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
for tax in tax_columns: for tax in tax_columns:
item_tax = itemised_tax.get(d.name, {}).get(tax, {}) item_tax = itemised_tax.get(d.name, {}).get(tax, {})
row.update({ row.update({
frappe.scrub(tax + ' Rate'): item_tax.get("tax_rate", 0), frappe.scrub(tax + ' Rate'): item_tax.get('tax_rate', 0),
frappe.scrub(tax + ' Amount'): item_tax.get("tax_amount", 0), frappe.scrub(tax + ' Amount'): item_tax.get('tax_amount', 0),
}) })
total_tax += flt(item_tax.get("tax_amount")) total_tax += flt(item_tax.get('tax_amount'))
row.update({ row.update({
'total_tax': total_tax, 'total_tax': total_tax,
@ -226,7 +233,7 @@ def get_columns(additional_table_columns, filters):
if filters.get('group_by') != 'Territory': if filters.get('group_by') != 'Territory':
columns.extend([ columns.extend([
{ {
'label': _("Territory"), 'label': _('Territory'),
'fieldname': 'territory', 'fieldname': 'territory',
'fieldtype': 'Link', 'fieldtype': 'Link',
'options': 'Territory', 'options': 'Territory',
@ -374,13 +381,12 @@ def get_items(filters, additional_query_columns):
`tabSales Invoice`.posting_date, `tabSales Invoice`.debit_to, `tabSales Invoice`.posting_date, `tabSales Invoice`.debit_to,
`tabSales Invoice`.project, `tabSales Invoice`.customer, `tabSales Invoice`.remarks, `tabSales Invoice`.project, `tabSales Invoice`.customer, `tabSales Invoice`.remarks,
`tabSales Invoice`.territory, `tabSales Invoice`.company, `tabSales Invoice`.base_net_total, `tabSales Invoice`.territory, `tabSales Invoice`.company, `tabSales Invoice`.base_net_total,
`tabSales Invoice Item`.item_code, `tabSales Invoice Item`.item_name, `tabSales Invoice Item`.item_code, `tabSales Invoice Item`.description,
`tabSales Invoice Item`.item_group, `tabSales Invoice Item`.description, `tabSales Invoice Item`.sales_order, `tabSales Invoice Item`.sales_order, `tabSales Invoice Item`.delivery_note,
`tabSales Invoice Item`.delivery_note, `tabSales Invoice Item`.income_account, `tabSales Invoice Item`.income_account, `tabSales Invoice Item`.cost_center,
`tabSales Invoice Item`.cost_center, `tabSales Invoice Item`.stock_qty, `tabSales Invoice Item`.stock_qty, `tabSales Invoice Item`.stock_uom,
`tabSales Invoice Item`.stock_uom, `tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount,
`tabSales Invoice Item`.base_net_amount, `tabSales Invoice`.customer_name, `tabSales Invoice`.customer_name, `tabSales Invoice`.customer_group, `tabSales Invoice Item`.so_detail,
`tabSales Invoice`.customer_group, `tabSales Invoice Item`.so_detail,
`tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {0} `tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {0}
from `tabSales Invoice`, `tabSales Invoice Item` from `tabSales Invoice`, `tabSales Invoice Item`
where `tabSales Invoice`.name = `tabSales Invoice Item`.parent where `tabSales Invoice`.name = `tabSales Invoice Item`.parent
@ -417,14 +423,14 @@ def get_deducted_taxes():
return frappe.db.sql_list("select name from `tabPurchase Taxes and Charges` where add_deduct_tax = 'Deduct'") return frappe.db.sql_list("select name from `tabPurchase Taxes and Charges` where add_deduct_tax = 'Deduct'")
def get_tax_accounts(item_list, columns, company_currency, def get_tax_accounts(item_list, columns, company_currency,
doctype="Sales Invoice", tax_doctype="Sales Taxes and Charges"): doctype='Sales Invoice', tax_doctype='Sales Taxes and Charges'):
import json import json
item_row_map = {} item_row_map = {}
tax_columns = [] tax_columns = []
invoice_item_row = {} invoice_item_row = {}
itemised_tax = {} itemised_tax = {}
tax_amount_precision = get_field_precision(frappe.get_meta(tax_doctype).get_field("tax_amount"), tax_amount_precision = get_field_precision(frappe.get_meta(tax_doctype).get_field('tax_amount'),
currency=company_currency) or 2 currency=company_currency) or 2
for d in item_list: for d in item_list:
@ -469,8 +475,8 @@ def get_tax_accounts(item_list, columns, company_currency,
tax_rate = tax_data tax_rate = tax_data
tax_amount = 0 tax_amount = 0
if charge_type == "Actual" and not tax_rate: if charge_type == 'Actual' and not tax_rate:
tax_rate = "NA" tax_rate = 'NA'
item_net_amount = sum([flt(d.base_net_amount) item_net_amount = sum([flt(d.base_net_amount)
for d in item_row_map.get(parent, {}).get(item_code, [])]) for d in item_row_map.get(parent, {}).get(item_code, [])])
@ -484,17 +490,17 @@ def get_tax_accounts(item_list, columns, company_currency,
if (doctype == 'Purchase Invoice' and name in deducted_tax) else tax_value) if (doctype == 'Purchase Invoice' and name in deducted_tax) else tax_value)
itemised_tax.setdefault(d.name, {})[description] = frappe._dict({ itemised_tax.setdefault(d.name, {})[description] = frappe._dict({
"tax_rate": tax_rate, 'tax_rate': tax_rate,
"tax_amount": tax_value 'tax_amount': tax_value
}) })
except ValueError: except ValueError:
continue continue
elif charge_type == "Actual" and tax_amount: elif charge_type == 'Actual' and tax_amount:
for d in invoice_item_row.get(parent, []): for d in invoice_item_row.get(parent, []):
itemised_tax.setdefault(d.name, {})[description] = frappe._dict({ itemised_tax.setdefault(d.name, {})[description] = frappe._dict({
"tax_rate": "NA", 'tax_rate': 'NA',
"tax_amount": flt((tax_amount * d.base_net_amount) / d.base_net_total, 'tax_amount': flt((tax_amount * d.base_net_amount) / d.base_net_total,
tax_amount_precision) tax_amount_precision)
}) })
@ -563,7 +569,7 @@ def add_total_row(data, filters, prev_group_by_value, item, total_row_map,
}) })
total_row_map.setdefault('total_row', { total_row_map.setdefault('total_row', {
subtotal_display_field: "Total", subtotal_display_field: 'Total',
'stock_qty': 0.0, 'stock_qty': 0.0,
'amount': 0.0, 'amount': 0.0,
'bold': 1, 'bold': 1,

@ -75,24 +75,23 @@ def get_data(filters):
for asset in assets_record: for asset in assets_record:
asset_value = asset.gross_purchase_amount - flt(asset.opening_accumulated_depreciation) \ asset_value = asset.gross_purchase_amount - flt(asset.opening_accumulated_depreciation) \
- flt(depreciation_amount_map.get(asset.name)) - flt(depreciation_amount_map.get(asset.name))
if asset_value: row = {
row = { "asset_id": asset.asset_id,
"asset_id": asset.asset_id, "asset_name": asset.asset_name,
"asset_name": asset.asset_name, "status": asset.status,
"status": asset.status, "department": asset.department,
"department": asset.department, "cost_center": asset.cost_center,
"cost_center": asset.cost_center, "vendor_name": pr_supplier_map.get(asset.purchase_receipt) or pi_supplier_map.get(asset.purchase_invoice),
"vendor_name": pr_supplier_map.get(asset.purchase_receipt) or pi_supplier_map.get(asset.purchase_invoice), "gross_purchase_amount": asset.gross_purchase_amount,
"gross_purchase_amount": asset.gross_purchase_amount, "opening_accumulated_depreciation": asset.opening_accumulated_depreciation,
"opening_accumulated_depreciation": asset.opening_accumulated_depreciation, "depreciated_amount": depreciation_amount_map.get(asset.asset_id) or 0.0,
"depreciated_amount": depreciation_amount_map.get(asset.asset_id) or 0.0, "available_for_use_date": asset.available_for_use_date,
"available_for_use_date": asset.available_for_use_date, "location": asset.location,
"location": asset.location, "asset_category": asset.asset_category,
"asset_category": asset.asset_category, "purchase_date": asset.purchase_date,
"purchase_date": asset.purchase_date, "asset_value": asset_value
"asset_value": asset_value }
} data.append(row)
data.append(row)
return data return data

@ -1,23 +1,31 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors // Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt // For license information, please see license.txt
cur_frm.add_fetch("contract_template", "contract_terms", "contract_terms");
cur_frm.add_fetch("contract_template", "requires_fulfilment", "requires_fulfilment");
// Add fulfilment terms from contract template into contract
frappe.ui.form.on("Contract", { frappe.ui.form.on("Contract", {
contract_template: function (frm) { contract_template: function (frm) {
// Populate the fulfilment terms table from a contract template, if any
if (frm.doc.contract_template) { if (frm.doc.contract_template) {
frappe.model.with_doc("Contract Template", frm.doc.contract_template, function () { frappe.call({
var tabletransfer = frappe.model.get_doc("Contract Template", frm.doc.contract_template); method: 'erpnext.crm.doctype.contract_template.contract_template.get_contract_template',
args: {
frm.doc.fulfilment_terms = []; template_name: frm.doc.contract_template,
$.each(tabletransfer.fulfilment_terms, function (index, row) { doc: frm.doc
var d = frm.add_child("fulfilment_terms"); },
d.requirement = row.requirement; callback: function(r) {
frm.refresh_field("fulfilment_terms"); if (r && r.message) {
}); let contract_template = r.message.contract_template;
frm.set_value("contract_terms", r.message.contract_terms);
frm.set_value("requires_fulfilment", contract_template.requires_fulfilment);
if (frm.doc.requires_fulfilment) {
// Populate the fulfilment terms table from a contract template, if any
r.message.contract_template.fulfilment_terms.forEach(element => {
let d = frm.add_child("fulfilment_terms");
d.requirement = element.requirement;
});
frm.refresh_field("fulfilment_terms");
}
}
}
}); });
} }
} }

@ -1,4 +1,5 @@
{ {
"actions": [],
"allow_import": 1, "allow_import": 1,
"allow_rename": 1, "allow_rename": 1,
"creation": "2018-04-12 06:32:04.582486", "creation": "2018-04-12 06:32:04.582486",
@ -247,7 +248,7 @@
], ],
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2020-03-30 06:56:07.257932", "modified": "2020-12-07 11:15:58.385521",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "CRM", "module": "CRM",
"name": "Contract", "name": "Contract",

@ -11,7 +11,9 @@
"contract_terms", "contract_terms",
"sb_fulfilment", "sb_fulfilment",
"requires_fulfilment", "requires_fulfilment",
"fulfilment_terms" "fulfilment_terms",
"section_break_6",
"contract_template_help"
], ],
"fields": [ "fields": [
{ {
@ -41,10 +43,20 @@
"fieldtype": "Table", "fieldtype": "Table",
"label": "Fulfilment Terms and Conditions", "label": "Fulfilment Terms and Conditions",
"options": "Contract Template Fulfilment Terms" "options": "Contract Template Fulfilment Terms"
},
{
"fieldname": "section_break_6",
"fieldtype": "Section Break"
},
{
"fieldname": "contract_template_help",
"fieldtype": "HTML",
"label": "Contract Template Help",
"options": "<h4>Contract Template Example</h4>\n\n<pre>Contract for Customer {{ party_name }}\n\n-Valid From : {{ start_date }} \n-Valid To : {{ end_date }}\n</pre>\n\n<h4>How to get fieldnames</h4>\n\n<p>The field names you can use in your Contract Template are the fields in the Contract for which you are creating the template. You can find out the fields of any documents via Setup &gt; Customize Form View and selecting the document type (e.g. Contract)</p>\n\n<h4>Templating</h4>\n\n<p>Templates are compiled using the Jinja Templating Language. To learn more about Jinja, <a class=\"strong\" href=\"http://jinja.pocoo.org/docs/dev/templates/\">read this documentation.</a></p>"
} }
], ],
"links": [], "links": [],
"modified": "2020-11-11 17:49:44.879363", "modified": "2020-12-07 10:44:22.587047",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "CRM", "module": "CRM",
"name": "Contract Template", "name": "Contract Template",

@ -5,6 +5,27 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils.jinja import validate_template
from six import string_types
import json
class ContractTemplate(Document): class ContractTemplate(Document):
pass def validate(self):
if self.contract_terms:
validate_template(self.contract_terms)
@frappe.whitelist()
def get_contract_template(template_name, doc):
if isinstance(doc, string_types):
doc = json.loads(doc)
contract_template = frappe.get_doc("Contract Template", template_name)
contract_terms = None
if contract_template.contract_terms:
contract_terms = frappe.render_template(contract_template.contract_terms, doc)
return {
'contract_template': contract_template,
'contract_terms': contract_terms
}

@ -10,8 +10,8 @@ from frappe.utils.nestedset import get_descendants_of
def execute(filters=None): def execute(filters=None):
filters = frappe._dict(filters or {}) filters = frappe._dict(filters or {})
if filters.from_date > filters.to_date: if filters.from_date > filters.to_date:
frappe.throw(_('From Date cannot be greater than To Date')) frappe.throw(_("From Date cannot be greater than To Date"))
columns = get_columns(filters) columns = get_columns(filters)
data = get_data(filters) data = get_data(filters)
@ -148,14 +148,16 @@ def get_data(filters):
company_list.append(filters.get("company")) company_list.append(filters.get("company"))
customer_details = get_customer_details() customer_details = get_customer_details()
item_details = get_item_details()
sales_order_records = get_sales_order_details(company_list, filters) sales_order_records = get_sales_order_details(company_list, filters)
for record in sales_order_records: for record in sales_order_records:
customer_record = customer_details.get(record.customer) customer_record = customer_details.get(record.customer)
item_record = item_details.get(record.item_code)
row = { row = {
"item_code": record.item_code, "item_code": record.item_code,
"item_name": record.item_name, "item_name": item_record.item_name,
"item_group": record.item_group, "item_group": item_record.item_group,
"description": record.description, "description": record.description,
"quantity": record.qty, "quantity": record.qty,
"uom": record.uom, "uom": record.uom,
@ -196,8 +198,8 @@ def get_conditions(filters):
return conditions return conditions
def get_customer_details(): def get_customer_details():
details = frappe.get_all('Customer', details = frappe.get_all("Customer",
fields=['name', 'customer_name', "customer_group"]) fields=["name", "customer_name", "customer_group"])
customer_details = {} customer_details = {}
for d in details: for d in details:
customer_details.setdefault(d.name, frappe._dict({ customer_details.setdefault(d.name, frappe._dict({
@ -206,15 +208,25 @@ def get_customer_details():
})) }))
return customer_details return customer_details
def get_item_details():
details = frappe.db.get_all("Item",
fields=["item_code", "item_name", "item_group"])
item_details = {}
for d in details:
item_details.setdefault(d.item_code, frappe._dict({
"item_name": d.item_name,
"item_group": d.item_group
}))
return item_details
def get_sales_order_details(company_list, filters): def get_sales_order_details(company_list, filters):
conditions = get_conditions(filters) conditions = get_conditions(filters)
return frappe.db.sql(""" return frappe.db.sql("""
SELECT SELECT
so_item.item_code, so_item.item_name, so_item.item_group, so_item.item_code, so_item.description, so_item.qty,
so_item.description, so_item.qty, so_item.uom, so_item.uom, so_item.base_rate, so_item.base_amount,
so_item.base_rate, so_item.base_amount, so.name, so.name, so.transaction_date, so.customer,so.territory,
so.transaction_date, so.customer, so.territory,
so.project, so_item.delivered_qty, so.project, so_item.delivered_qty,
so_item.billed_amt, so.company so_item.billed_amt, so.company
FROM FROM