Merge branch 'develop' of https://github.com/frappe/erpnext into rebrand-ui
This commit is contained in:
commit
dc13d4b0fc
@ -14,7 +14,6 @@
|
|||||||
"column_break_9",
|
"column_break_9",
|
||||||
"update_stock",
|
"update_stock",
|
||||||
"ignore_pricing_rule",
|
"ignore_pricing_rule",
|
||||||
"hide_unavailable_items",
|
|
||||||
"warehouse",
|
"warehouse",
|
||||||
"campaign",
|
"campaign",
|
||||||
"company_address",
|
"company_address",
|
||||||
@ -23,6 +22,9 @@
|
|||||||
"section_break_11",
|
"section_break_11",
|
||||||
"payments",
|
"payments",
|
||||||
"section_break_14",
|
"section_break_14",
|
||||||
|
"hide_images",
|
||||||
|
"hide_unavailable_items",
|
||||||
|
"auto_add_item_to_cart",
|
||||||
"item_groups",
|
"item_groups",
|
||||||
"column_break_16",
|
"column_break_16",
|
||||||
"customer_groups",
|
"customer_groups",
|
||||||
@ -124,7 +126,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_14",
|
"fieldname": "section_break_14",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Configuration"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Only show Items from these Item Groups",
|
"description": "Only show Items from these Item Groups",
|
||||||
@ -314,13 +317,25 @@
|
|||||||
"fieldname": "hide_unavailable_items",
|
"fieldname": "hide_unavailable_items",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Hide Unavailable Items"
|
"label": "Hide Unavailable Items"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "hide_images",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Hide Images"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "auto_add_item_to_cart",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Automatically Add Filtered Item To Cart"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon-cog",
|
"icon": "icon-cog",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-10-29 13:18:38.795925",
|
"modified": "2020-12-10 13:59:28.877572",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "POS Profile",
|
"name": "POS Profile",
|
||||||
|
|||||||
@ -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 > 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
|
||||||
|
}
|
||||||
@ -408,7 +408,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
|
|
||||||
show_description(row_to_modify.idx, row_to_modify.item_code);
|
show_description(row_to_modify.idx, row_to_modify.item_code);
|
||||||
|
|
||||||
this.frm.from_barcode = true;
|
this.frm.from_barcode = this.frm.from_barcode ? this.frm.from_barcode + 1 : 1;
|
||||||
frappe.model.set_value(row_to_modify.doctype, row_to_modify.name, {
|
frappe.model.set_value(row_to_modify.doctype, row_to_modify.name, {
|
||||||
item_code: data.item_code,
|
item_code: data.item_code,
|
||||||
qty: (row_to_modify.qty || 0) + 1
|
qty: (row_to_modify.qty || 0) + 1
|
||||||
@ -493,7 +493,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
d.item_code = "";
|
d.item_code = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
this.frm.from_barcode = true;
|
this.frm.from_barcode = this.frm.from_barcode ? this.frm.from_barcode + 1 : 1;
|
||||||
this.item_code(doc, cdt, cdn);
|
this.item_code(doc, cdt, cdn);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -510,11 +510,12 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
show_batch_dialog = 1;
|
show_batch_dialog = 1;
|
||||||
}
|
}
|
||||||
// clear barcode if setting item (else barcode will take priority)
|
// clear barcode if setting item (else barcode will take priority)
|
||||||
if(!this.frm.from_barcode) {
|
if (this.frm.from_barcode == 0) {
|
||||||
item.barcode = null;
|
item.barcode = null;
|
||||||
}
|
}
|
||||||
|
this.frm.from_barcode = this.frm.from_barcode - 1 >= 0 ? this.frm.from_barcode - 1 : 0;
|
||||||
|
|
||||||
|
|
||||||
this.frm.from_barcode = false;
|
|
||||||
if(item.item_code || item.barcode || item.serial_no) {
|
if(item.item_code || item.barcode || item.serial_no) {
|
||||||
if(!this.validate_company_and_party()) {
|
if(!this.validate_company_and_party()) {
|
||||||
this.frm.fields_dict["items"].grid.grid_rows[item.idx - 1].remove();
|
this.frm.fields_dict["items"].grid.grid_rows[item.idx - 1].remove();
|
||||||
|
|||||||
@ -98,24 +98,24 @@ erpnext.PointOfSale.Controller = class {
|
|||||||
dialog.show();
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare_app_defaults(data) {
|
async prepare_app_defaults(data) {
|
||||||
this.pos_opening = data.name;
|
this.pos_opening = data.name;
|
||||||
this.company = data.company;
|
this.company = data.company;
|
||||||
this.pos_profile = data.pos_profile;
|
this.pos_profile = data.pos_profile;
|
||||||
this.pos_opening_time = data.period_start_date;
|
this.pos_opening_time = data.period_start_date;
|
||||||
|
this.item_stock_map = {};
|
||||||
|
this.settings = {};
|
||||||
|
|
||||||
frappe.db.get_value('Stock Settings', undefined, 'allow_negative_stock').then(({ message }) => {
|
frappe.db.get_value('Stock Settings', undefined, 'allow_negative_stock').then(({ message }) => {
|
||||||
this.allow_negative_stock = flt(message.allow_negative_stock) || false;
|
this.allow_negative_stock = flt(message.allow_negative_stock) || false;
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.db.get_doc("POS Profile", this.pos_profile).then((profile) => {
|
frappe.db.get_doc("POS Profile", this.pos_profile).then((profile) => {
|
||||||
this.customer_groups = profile.customer_groups.map(group => group.customer_group);
|
this.settings.customer_groups = profile.customer_groups.map(group => group.customer_group);
|
||||||
this.cart.make_customer_selector();
|
this.settings.hide_images = profile.hide_images;
|
||||||
|
this.settings.auto_add_item_to_cart = profile.auto_add_item_to_cart;
|
||||||
|
this.make_app();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.item_stock_map = {};
|
|
||||||
|
|
||||||
this.make_app();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
make_app() {
|
make_app() {
|
||||||
@ -208,12 +208,11 @@ erpnext.PointOfSale.Controller = class {
|
|||||||
this.item_selector = new erpnext.PointOfSale.ItemSelector({
|
this.item_selector = new erpnext.PointOfSale.ItemSelector({
|
||||||
wrapper: this.$components_wrapper,
|
wrapper: this.$components_wrapper,
|
||||||
pos_profile: this.pos_profile,
|
pos_profile: this.pos_profile,
|
||||||
|
settings: this.settings,
|
||||||
events: {
|
events: {
|
||||||
item_selected: args => this.on_cart_update(args),
|
item_selected: args => this.on_cart_update(args),
|
||||||
|
|
||||||
get_frm: () => this.frm || {},
|
get_frm: () => this.frm || {}
|
||||||
|
|
||||||
get_allowed_item_group: () => this.item_groups
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -221,6 +220,7 @@ erpnext.PointOfSale.Controller = class {
|
|||||||
init_item_cart() {
|
init_item_cart() {
|
||||||
this.cart = new erpnext.PointOfSale.ItemCart({
|
this.cart = new erpnext.PointOfSale.ItemCart({
|
||||||
wrapper: this.$components_wrapper,
|
wrapper: this.$components_wrapper,
|
||||||
|
settings: this.settings,
|
||||||
events: {
|
events: {
|
||||||
get_frm: () => this.frm,
|
get_frm: () => this.frm,
|
||||||
|
|
||||||
@ -243,9 +243,7 @@ erpnext.PointOfSale.Controller = class {
|
|||||||
this.customer_details = details;
|
this.customer_details = details;
|
||||||
// will add/remove LP payment method
|
// will add/remove LP payment method
|
||||||
this.payment.render_loyalty_points_payment_mode();
|
this.payment.render_loyalty_points_payment_mode();
|
||||||
},
|
}
|
||||||
|
|
||||||
get_allowed_customer_group: () => this.customer_groups
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
erpnext.PointOfSale.ItemCart = class {
|
erpnext.PointOfSale.ItemCart = class {
|
||||||
constructor({ wrapper, events }) {
|
constructor({ wrapper, events, settings }) {
|
||||||
this.wrapper = wrapper;
|
this.wrapper = wrapper;
|
||||||
this.events = events;
|
this.events = events;
|
||||||
this.customer_info = undefined;
|
this.customer_info = undefined;
|
||||||
|
this.hide_images = settings.hide_images;
|
||||||
|
this.allowed_customer_groups = settings.customer_groups;
|
||||||
|
|
||||||
this.init_component();
|
this.init_component();
|
||||||
}
|
}
|
||||||
|
|
||||||
init_component() {
|
init_component() {
|
||||||
this.prepare_dom();
|
this.prepare_dom();
|
||||||
this.init_child_components();
|
this.init_child_components();
|
||||||
@ -32,15 +34,16 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
`<div class="customer-section"></div>`
|
`<div class="customer-section"></div>`
|
||||||
)
|
)
|
||||||
this.$customer_section = this.$component.find('.customer-section');
|
this.$customer_section = this.$component.find('.customer-section');
|
||||||
|
this.make_customer_selector();
|
||||||
}
|
}
|
||||||
|
|
||||||
reset_customer_selector() {
|
reset_customer_selector() {
|
||||||
const frm = this.events.get_frm();
|
const frm = this.events.get_frm();
|
||||||
frm.set_value('customer', '');
|
frm.set_value('customer', '');
|
||||||
this.make_customer_selector();
|
this.make_customer_selector();
|
||||||
this.customer_field.set_focus();
|
this.customer_field.set_focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
init_cart_components() {
|
init_cart_components() {
|
||||||
this.$component.append(
|
this.$component.append(
|
||||||
`<div class="cart-container">
|
`<div class="cart-container">
|
||||||
@ -54,7 +57,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
<div class="cart-items-section"></div>
|
<div class="cart-items-section"></div>
|
||||||
<div class="cart-totals-section"></div>
|
<div class="cart-totals-section"></div>
|
||||||
<div class="numpad-section"></div>
|
<div class="numpad-section"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
this.$cart_container = this.$component.find('.cart-container');
|
this.$cart_container = this.$component.find('.cart-container');
|
||||||
@ -70,7 +73,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
|
|
||||||
this.make_no_items_placeholder();
|
this.make_no_items_placeholder();
|
||||||
}
|
}
|
||||||
|
|
||||||
make_no_items_placeholder() {
|
make_no_items_placeholder() {
|
||||||
this.$cart_header.css('display', 'none');
|
this.$cart_header.css('display', 'none');
|
||||||
this.$cart_items_wrapper.html(
|
this.$cart_items_wrapper.html(
|
||||||
@ -111,7 +114,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
|
|
||||||
this.$add_discount_elem = this.$component.find(".add-discount-wrapper");
|
this.$add_discount_elem = this.$component.find(".add-discount-wrapper");
|
||||||
}
|
}
|
||||||
|
|
||||||
make_cart_numpad() {
|
make_cart_numpad() {
|
||||||
this.$numpad_section = this.$component.find('.numpad-section');
|
this.$numpad_section = this.$component.find('.numpad-section');
|
||||||
|
|
||||||
@ -147,7 +150,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
`<div class="numpad-btn checkout-btn" data-button-value="checkout">Checkout</div>`
|
`<div class="numpad-btn checkout-btn" data-button-value="checkout">Checkout</div>`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
bind_events() {
|
bind_events() {
|
||||||
const me = this;
|
const me = this;
|
||||||
this.$customer_section.on('click', '.reset-customer-btn', function (e) {
|
this.$customer_section.on('click', '.reset-customer-btn', function (e) {
|
||||||
@ -186,7 +189,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
|
|
||||||
this.$component.on('click', '.checkout-btn', function() {
|
this.$component.on('click', '.checkout-btn', function() {
|
||||||
if ($(this).attr('style').indexOf('--blue-500') == -1) return;
|
if ($(this).attr('style').indexOf('--blue-500') == -1) return;
|
||||||
|
|
||||||
me.events.checkout();
|
me.events.checkout();
|
||||||
me.toggle_checkout_btn(false);
|
me.toggle_checkout_btn(false);
|
||||||
});
|
});
|
||||||
@ -219,7 +222,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
if (btn === '.') shortcut_key = 'ctrl+>';
|
if (btn === '.') shortcut_key = 'ctrl+>';
|
||||||
|
|
||||||
// to account for fieldname map
|
// to account for fieldname map
|
||||||
const fieldname = this.number_pad.fieldnames[btn] ? this.number_pad.fieldnames[btn] :
|
const fieldname = this.number_pad.fieldnames[btn] ? this.number_pad.fieldnames[btn] :
|
||||||
typeof btn === 'string' ? frappe.scrub(btn) : btn;
|
typeof btn === 'string' ? frappe.scrub(btn) : btn;
|
||||||
|
|
||||||
let shortcut_label = shortcut_key.split('+').map(frappe.utils.to_title_case).join('+');
|
let shortcut_label = shortcut_key.split('+').map(frappe.utils.to_title_case).join('+');
|
||||||
@ -230,7 +233,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
const cart_is_visible = this.$component.is(":visible");
|
const cart_is_visible = this.$component.is(":visible");
|
||||||
if (cart_is_visible && this.item_is_selected && this.$numpad_section.is(":visible")) {
|
if (cart_is_visible && this.item_is_selected && this.$numpad_section.is(":visible")) {
|
||||||
this.$numpad_section.find(`.numpad-btn[data-button-value="${fieldname}"]`).click();
|
this.$numpad_section.find(`.numpad-btn[data-button-value="${fieldname}"]`).click();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,7 +271,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle_item_highlight(item) {
|
toggle_item_highlight(item) {
|
||||||
const $cart_item = $(item);
|
const $cart_item = $(item);
|
||||||
const item_is_highlighted = $cart_item.attr("style") == "background-color:var(--gray-50);";
|
const item_is_highlighted = $cart_item.attr("style") == "background-color:var(--gray-50);";
|
||||||
@ -289,7 +292,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
`);
|
`);
|
||||||
const me = this;
|
const me = this;
|
||||||
const query = { query: 'erpnext.controllers.queries.customer_query' };
|
const query = { query: 'erpnext.controllers.queries.customer_query' };
|
||||||
const allowed_customer_group = this.events.get_allowed_customer_group() || [];
|
const allowed_customer_group = this.allowed_customer_groups || [];
|
||||||
if (allowed_customer_group.length) {
|
if (allowed_customer_group.length) {
|
||||||
query.filters = {
|
query.filters = {
|
||||||
customer_group: ['in', allowed_customer_group]
|
customer_group: ['in', allowed_customer_group]
|
||||||
@ -324,7 +327,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
});
|
});
|
||||||
this.customer_field.toggle_label(false);
|
this.customer_field.toggle_label(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch_customer_details(customer) {
|
fetch_customer_details(customer) {
|
||||||
if (customer) {
|
if (customer) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
@ -411,9 +414,9 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_customer_section() {
|
update_customer_section() {
|
||||||
const { customer, email_id='', mobile_no='' } = this.customer_info || {};
|
const { customer, email_id='', mobile_no='', image } = this.customer_info || {};
|
||||||
|
|
||||||
if (customer) {
|
if (customer) {
|
||||||
this.$customer_section.html(
|
this.$customer_section.html(
|
||||||
@ -459,7 +462,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
return `<div class="customer-image customer-abbr">${frappe.get_abbr(customer)}</div>`
|
return `<div class="customer-image customer-abbr">${frappe.get_abbr(customer)}</div>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_totals_section(frm) {
|
update_totals_section(frm) {
|
||||||
if (!frm) frm = this.events.get_frm();
|
if (!frm) frm = this.events.get_frm();
|
||||||
|
|
||||||
@ -469,7 +472,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
const taxes = frm.doc.taxes.map(t => { return { description: t.description, rate: t.rate }})
|
const taxes = frm.doc.taxes.map(t => { return { description: t.description, rate: t.rate }})
|
||||||
this.render_taxes(frm.doc.base_total_taxes_and_charges, taxes);
|
this.render_taxes(frm.doc.base_total_taxes_and_charges, taxes);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_net_total(value) {
|
render_net_total(value) {
|
||||||
const currency = this.events.get_frm().doc.currency;
|
const currency = this.events.get_frm().doc.currency;
|
||||||
this.$totals_section.find('.net-total-container').html(
|
this.$totals_section.find('.net-total-container').html(
|
||||||
@ -480,7 +483,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
`<div>Net Total: <span>${format_currency(value, currency)}</span></div>`
|
`<div>Net Total: <span>${format_currency(value, currency)}</span></div>`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_grand_total(value) {
|
render_grand_total(value) {
|
||||||
const currency = this.events.get_frm().doc.currency;
|
const currency = this.events.get_frm().doc.currency;
|
||||||
this.$totals_section.find('.grand-total-container').html(
|
this.$totals_section.find('.grand-total-container').html(
|
||||||
@ -518,12 +521,12 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
const item_code_attr = `[data-item-code="${escape(item_code)}"]`;
|
const item_code_attr = `[data-item-code="${escape(item_code)}"]`;
|
||||||
const uom_attr = `[data-uom=${escape(uom)}]`;
|
const uom_attr = `[data-uom=${escape(uom)}]`;
|
||||||
|
|
||||||
const item_selector = batch_no ?
|
const item_selector = batch_no ?
|
||||||
`.cart-item-wrapper${batch_attr}${uom_attr}` : `.cart-item-wrapper${item_code_attr}${uom_attr}`;
|
`.cart-item-wrapper${batch_attr}${uom_attr}` : `.cart-item-wrapper${item_code_attr}${uom_attr}`;
|
||||||
|
|
||||||
return this.$cart_items_wrapper.find(item_selector);
|
return this.$cart_items_wrapper.find(item_selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_item_html(item, remove_item) {
|
update_item_html(item, remove_item) {
|
||||||
const $item = this.get_cart_item(item);
|
const $item = this.get_cart_item(item);
|
||||||
|
|
||||||
@ -534,7 +537,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
const search_field = batch_no ? 'batch_no' : 'item_code';
|
const search_field = batch_no ? 'batch_no' : 'item_code';
|
||||||
const search_value = batch_no || item_code;
|
const search_value = batch_no || item_code;
|
||||||
const item_row = this.events.get_frm().doc.items.find(i => i[search_field] === search_value && i.uom === uom);
|
const item_row = this.events.get_frm().doc.items.find(i => i[search_field] === search_value && i.uom === uom);
|
||||||
|
|
||||||
this.render_cart_item(item_row, $item);
|
this.render_cart_item(item_row, $item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,14 +546,14 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
|
|
||||||
this.update_empty_cart_section(no_of_cart_items);
|
this.update_empty_cart_section(no_of_cart_items);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_cart_item(item_data, $item_to_update) {
|
render_cart_item(item_data, $item_to_update) {
|
||||||
const currency = this.events.get_frm().doc.currency;
|
const currency = this.events.get_frm().doc.currency;
|
||||||
const me = this;
|
const me = this;
|
||||||
|
|
||||||
if (!$item_to_update.length) {
|
if (!$item_to_update.length) {
|
||||||
this.$cart_items_wrapper.append(
|
this.$cart_items_wrapper.append(
|
||||||
`<div class="cart-item-wrapper"
|
`<div class="cart-item-wrapper"
|
||||||
data-item-code="${escape(item_data.item_code)}" data-uom="${escape(item_data.uom)}"
|
data-item-code="${escape(item_data.item_code)}" data-uom="${escape(item_data.uom)}"
|
||||||
data-batch-no="${escape(item_data.batch_no || '')}">
|
data-batch-no="${escape(item_data.batch_no || '')}">
|
||||||
</div>
|
</div>
|
||||||
@ -589,7 +592,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
me.$cart_header.find(".rate-amount-header").css("width", max_width);
|
me.$cart_header.find(".rate-amount-header").css("width", max_width);
|
||||||
me.$cart_items_wrapper.find(".item-rate-amount").css("width", max_width);
|
me.$cart_items_wrapper.find(".item-rate-amount").css("width", max_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_rate_discount_html() {
|
function get_rate_discount_html() {
|
||||||
if (item_data.rate && item_data.amount && item_data.rate !== item_data.amount) {
|
if (item_data.rate && item_data.amount && item_data.rate !== item_data.amount) {
|
||||||
return `
|
return `
|
||||||
@ -641,7 +644,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
const scrollTop = $item.offset().top - this.$cart_items_wrapper.offset().top + this.$cart_items_wrapper.scrollTop();
|
const scrollTop = $item.offset().top - this.$cart_items_wrapper.offset().top + this.$cart_items_wrapper.scrollTop();
|
||||||
this.$cart_items_wrapper.animate({ scrollTop });
|
this.$cart_items_wrapper.animate({ scrollTop });
|
||||||
}
|
}
|
||||||
|
|
||||||
update_selector_value_in_cart_item(selector, value, item) {
|
update_selector_value_in_cart_item(selector, value, item) {
|
||||||
const $item_to_update = this.get_cart_item(item);
|
const $item_to_update = this.get_cart_item(item);
|
||||||
$item_to_update.attr(`data-${selector}`, value);
|
$item_to_update.attr(`data-${selector}`, value);
|
||||||
@ -670,7 +673,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_empty_cart_section(no_of_cart_items) {
|
update_empty_cart_section(no_of_cart_items) {
|
||||||
const $no_item_element = this.$cart_items_wrapper.find('.no-item-wrapper');
|
const $no_item_element = this.$cart_items_wrapper.find('.no-item-wrapper');
|
||||||
|
|
||||||
@ -679,7 +682,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
|
|
||||||
no_of_cart_items === 0 && !$no_item_element.length && this.make_no_items_placeholder();
|
no_of_cart_items === 0 && !$no_item_element.length && this.make_no_items_placeholder();
|
||||||
}
|
}
|
||||||
|
|
||||||
on_numpad_event($btn) {
|
on_numpad_event($btn) {
|
||||||
const current_action = $btn.attr('data-button-value');
|
const current_action = $btn.attr('data-button-value');
|
||||||
const action_is_field_edit = ['qty', 'discount_percentage', 'rate'].includes(current_action);
|
const action_is_field_edit = ['qty', 'discount_percentage', 'rate'].includes(current_action);
|
||||||
@ -698,7 +701,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
this.prev_action = undefined;
|
this.prev_action = undefined;
|
||||||
}
|
}
|
||||||
this.numpad_value = '';
|
this.numpad_value = '';
|
||||||
|
|
||||||
} else if (current_action === 'checkout') {
|
} else if (current_action === 'checkout') {
|
||||||
this.prev_action = undefined;
|
this.prev_action = undefined;
|
||||||
this.toggle_item_highlight();
|
this.toggle_item_highlight();
|
||||||
@ -724,7 +727,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
frappe.utils.play_sound("error");
|
frappe.utils.play_sound("error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flt(this.numpad_value) > 100 && this.prev_action === 'discount_percentage') {
|
if (flt(this.numpad_value) > 100 && this.prev_action === 'discount_percentage') {
|
||||||
frappe.show_alert({
|
frappe.show_alert({
|
||||||
message: __('Discount cannot be greater than 100%'),
|
message: __('Discount cannot be greater than 100%'),
|
||||||
@ -736,7 +739,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
|
|
||||||
this.events.numpad_event(this.numpad_value, this.prev_action);
|
this.events.numpad_event(this.numpad_value, this.prev_action);
|
||||||
}
|
}
|
||||||
|
|
||||||
highlight_numpad_btn($btn, curr_action) {
|
highlight_numpad_btn($btn, curr_action) {
|
||||||
const curr_action_is_highlighted = $btn.hasClass('highlighted-numpad-btn');
|
const curr_action_is_highlighted = $btn.hasClass('highlighted-numpad-btn');
|
||||||
const curr_action_is_action = ['qty', 'discount_percentage', 'rate', 'done'].includes(curr_action);
|
const curr_action_is_action = ['qty', 'discount_percentage', 'rate', 'done'].includes(curr_action);
|
||||||
@ -901,7 +904,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetch_customer_transactions() {
|
fetch_customer_transactions() {
|
||||||
frappe.db.get_list('POS Invoice', {
|
frappe.db.get_list('POS Invoice', {
|
||||||
filters: { customer: this.customer_info.customer, docstatus: 1 },
|
filters: { customer: this.customer_info.customer, docstatus: 1 },
|
||||||
fields: ['name', 'grand_total', 'status', 'posting_date', 'posting_time', 'currency'],
|
fields: ['name', 'grand_total', 'status', 'posting_date', 'posting_time', 'currency'],
|
||||||
limit: 20
|
limit: 20
|
||||||
@ -956,7 +959,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
this.events.customer_details_updated(this.customer_info);
|
this.events.customer_details_updated(this.customer_info);
|
||||||
this.update_customer_section();
|
this.update_customer_section();
|
||||||
})
|
})
|
||||||
|
|
||||||
this.$cart_items_wrapper.html('');
|
this.$cart_items_wrapper.html('');
|
||||||
if (frm.doc.items.length) {
|
if (frm.doc.items.length) {
|
||||||
frm.doc.items.forEach(item => {
|
frm.doc.items.forEach(item => {
|
||||||
@ -983,5 +986,5 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
toggle_component(show) {
|
toggle_component(show) {
|
||||||
show ? this.$component.css('display', 'flex') : this.$component.css('display', 'none');
|
show ? this.$component.css('display', 'flex') : this.$component.css('display', 'none');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
import onScan from 'onscan.js';
|
import onScan from 'onscan.js';
|
||||||
|
|
||||||
erpnext.PointOfSale.ItemSelector = class {
|
erpnext.PointOfSale.ItemSelector = class {
|
||||||
constructor({ frm, wrapper, events, pos_profile }) {
|
constructor({ frm, wrapper, events, pos_profile, settings }) {
|
||||||
this.wrapper = wrapper;
|
this.wrapper = wrapper;
|
||||||
this.events = events;
|
this.events = events;
|
||||||
this.pos_profile = pos_profile;
|
this.pos_profile = pos_profile;
|
||||||
|
this.hide_images = settings.hide_images;
|
||||||
|
this.auto_add_item = settings.auto_add_item_to_cart;
|
||||||
|
|
||||||
this.inti_component();
|
this.inti_component();
|
||||||
}
|
}
|
||||||
|
|
||||||
inti_component() {
|
inti_component() {
|
||||||
this.prepare_dom();
|
this.prepare_dom();
|
||||||
this.make_search_bar();
|
this.make_search_bar();
|
||||||
@ -28,8 +30,9 @@ erpnext.PointOfSale.ItemSelector = class {
|
|||||||
<div class="items-container"></div>
|
<div class="items-container"></div>
|
||||||
</section>`
|
</section>`
|
||||||
);
|
);
|
||||||
|
|
||||||
this.$component = this.wrapper.find('.items-selector');
|
this.$component = this.wrapper.find('.items-selector');
|
||||||
|
this.$items_container = this.$component.find('.items-container');
|
||||||
}
|
}
|
||||||
|
|
||||||
async load_items_data() {
|
async load_items_data() {
|
||||||
@ -53,7 +56,7 @@ erpnext.PointOfSale.ItemSelector = class {
|
|||||||
let { item_group, pos_profile } = this;
|
let { item_group, pos_profile } = this;
|
||||||
|
|
||||||
!item_group && (item_group = this.parent_item_group);
|
!item_group && (item_group = this.parent_item_group);
|
||||||
|
|
||||||
return frappe.call({
|
return frappe.call({
|
||||||
method: "erpnext.selling.page.point_of_sale.point_of_sale.get_items",
|
method: "erpnext.selling.page.point_of_sale.point_of_sale.get_items",
|
||||||
freeze: true,
|
freeze: true,
|
||||||
@ -63,7 +66,6 @@ erpnext.PointOfSale.ItemSelector = class {
|
|||||||
|
|
||||||
|
|
||||||
render_item_list(items) {
|
render_item_list(items) {
|
||||||
this.$items_container = this.$component.find('.items-container');
|
|
||||||
this.$items_container.html('');
|
this.$items_container.html('');
|
||||||
|
|
||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
@ -73,14 +75,15 @@ erpnext.PointOfSale.ItemSelector = class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_item_html(item) {
|
get_item_html(item) {
|
||||||
|
const me = this;
|
||||||
const { item_image, serial_no, batch_no, barcode, actual_qty, stock_uom } = item;
|
const { item_image, serial_no, batch_no, barcode, actual_qty, stock_uom } = item;
|
||||||
const indicator_color = actual_qty > 10 ? "green" : actual_qty <= 0 ? "red" : "orange";
|
const indicator_color = actual_qty > 10 ? "green" : actual_qty <= 0 ? "red" : "orange";
|
||||||
|
|
||||||
function get_item_image_html() {
|
function get_item_image_html() {
|
||||||
if (item_image) {
|
if (!me.hide_images && item_image) {
|
||||||
return `<div class="item-display">
|
return `<div class="flex items-center justify-center h-32 border-b-grey text-6xl text-grey-100">
|
||||||
<img src="${item_image}" alt="${frappe.get_abbr(item.item_name)}">
|
<img class="h-full" src="${item_image}" alt="${frappe.get_abbr(item.item_name)}" style="object-fit: cover;">
|
||||||
</div>`;
|
</div>`
|
||||||
} else {
|
} else {
|
||||||
return `<div class="item-display abbr">${frappe.get_abbr(item.item_name)}</div>`;
|
return `<div class="item-display abbr">${frappe.get_abbr(item.item_name)}</div>`;
|
||||||
}
|
}
|
||||||
@ -166,7 +169,7 @@ erpnext.PointOfSale.ItemSelector = class {
|
|||||||
let batch_no = unescape($item.attr('data-batch-no'));
|
let batch_no = unescape($item.attr('data-batch-no'));
|
||||||
let serial_no = unescape($item.attr('data-serial-no'));
|
let serial_no = unescape($item.attr('data-serial-no'));
|
||||||
let uom = unescape($item.attr('data-uom'));
|
let uom = unescape($item.attr('data-uom'));
|
||||||
|
|
||||||
// escape(undefined) returns "undefined" then unescape returns "undefined"
|
// escape(undefined) returns "undefined" then unescape returns "undefined"
|
||||||
batch_no = batch_no === "undefined" ? undefined : batch_no;
|
batch_no = batch_no === "undefined" ? undefined : batch_no;
|
||||||
serial_no = serial_no === "undefined" ? undefined : serial_no;
|
serial_no = serial_no === "undefined" ? undefined : serial_no;
|
||||||
@ -204,6 +207,7 @@ erpnext.PointOfSale.ItemSelector = class {
|
|||||||
ignore_inputs: true,
|
ignore_inputs: true,
|
||||||
page: cur_page.page.page
|
page: cur_page.page.page
|
||||||
});
|
});
|
||||||
|
|
||||||
// for selecting the last filtered item on search
|
// for selecting the last filtered item on search
|
||||||
frappe.ui.keys.on("enter", () => {
|
frappe.ui.keys.on("enter", () => {
|
||||||
const selector_is_visible = this.$component.is(':visible');
|
const selector_is_visible = this.$component.is(':visible');
|
||||||
@ -225,7 +229,7 @@ erpnext.PointOfSale.ItemSelector = class {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
filter_items({ search_term='' }={}) {
|
filter_items({ search_term='' }={}) {
|
||||||
if (search_term) {
|
if (search_term) {
|
||||||
search_term = search_term.toLowerCase();
|
search_term = search_term.toLowerCase();
|
||||||
@ -236,6 +240,7 @@ erpnext.PointOfSale.ItemSelector = class {
|
|||||||
const items = this.search_index[search_term];
|
const items = this.search_index[search_term];
|
||||||
this.items = items;
|
this.items = items;
|
||||||
this.render_item_list(items);
|
this.render_item_list(items);
|
||||||
|
this.auto_add_item && this.items.length == 1 && this.add_filtered_item_to_cart();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,15 +253,20 @@ erpnext.PointOfSale.ItemSelector = class {
|
|||||||
}
|
}
|
||||||
this.items = items;
|
this.items = items;
|
||||||
this.render_item_list(items);
|
this.render_item_list(items);
|
||||||
|
this.auto_add_item && this.items.length == 1 && this.add_filtered_item_to_cart();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_filtered_item_to_cart() {
|
||||||
|
this.$items_container.find(".item-wrapper").click();
|
||||||
|
}
|
||||||
|
|
||||||
resize_selector(minimize) {
|
resize_selector(minimize) {
|
||||||
minimize ?
|
minimize ?
|
||||||
this.$component.find('.filter-section').css('grid-template-columns', 'repeat(1, minmax(0, 1fr))') :
|
this.$component.find('.filter-section').css('grid-template-columns', 'repeat(1, minmax(0, 1fr))') :
|
||||||
this.$component.find('.filter-section').css('grid-template-columns', 'repeat(12, minmax(0, 1fr))');
|
this.$component.find('.filter-section').css('grid-template-columns', 'repeat(12, minmax(0, 1fr))');
|
||||||
|
|
||||||
minimize ?
|
minimize ?
|
||||||
this.$component.find('.search-field').css('margin', 'var(--margin-sm) 0px') :
|
this.$component.find('.search-field').css('margin', 'var(--margin-sm) 0px') :
|
||||||
this.$component.find('.search-field').css('margin', '0px var(--margin-sm)');
|
this.$component.find('.search-field').css('margin', '0px var(--margin-sm)');
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -20,10 +20,10 @@
|
|||||||
{%- if (charge.tax_amount or print_settings.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}
|
{%- if (charge.tax_amount or print_settings.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-5 {%- if doc.align_labels_right %} text-right{%- endif -%}">
|
<div class="col-xs-5 {%- if doc.align_labels_right %} text-right{%- endif -%}">
|
||||||
<label>{{ charge.get_formatted("description") }}</label></div>
|
<label>{{ charge.get_formatted("description") }}</label>
|
||||||
|
</div>
|
||||||
<div class="col-xs-7 text-right">
|
<div class="col-xs-7 text-right">
|
||||||
{{ frappe.format_value(frappe.utils.flt(charge.tax_amount),
|
{{ charge.get_formatted('tax_amount', doc) }}
|
||||||
table_meta.get_field("tax_amount"), doc, currency=doc.currency) }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user