Merge branch 'develop' of https://github.com/frappe/erpnext into develop
@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '10.1.18'
|
||||
__version__ = '10.1.20'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
@ -17,18 +17,13 @@ frappe.ui.form.on('Account', {
|
||||
});
|
||||
},
|
||||
refresh: function(frm) {
|
||||
if (frm.doc.__islocal) {
|
||||
frappe.msgprint(__("Please create new account from Chart of Accounts."));
|
||||
throw "cannot create";
|
||||
}
|
||||
|
||||
frm.toggle_display('account_name', frm.doc.__islocal);
|
||||
frm.toggle_display('account_name', frm.is_new());
|
||||
|
||||
// hide fields if group
|
||||
frm.toggle_display(['account_type', 'tax_rate'], cint(frm.doc.is_group) == 0);
|
||||
|
||||
// disable fields
|
||||
frm.toggle_enable(['account_name', 'is_group', 'company'], false);
|
||||
frm.toggle_enable(['is_group', 'company'], false);
|
||||
|
||||
if (cint(frm.doc.is_group) == 0) {
|
||||
frm.toggle_display('freeze_account', frm.doc.__onload
|
||||
@ -36,19 +31,18 @@ frappe.ui.form.on('Account', {
|
||||
}
|
||||
|
||||
// read-only for root accounts
|
||||
if (!frm.doc.parent_account) {
|
||||
frm.set_read_only();
|
||||
frm.set_intro(__("This is a root account and cannot be edited."));
|
||||
} else {
|
||||
// credit days and type if customer or supplier
|
||||
frm.set_intro(null);
|
||||
frm.trigger('account_type');
|
||||
if (!frm.is_new()) {
|
||||
if (!frm.doc.parent_account) {
|
||||
frm.set_read_only();
|
||||
frm.set_intro(__("This is a root account and cannot be edited."));
|
||||
} else {
|
||||
// credit days and type if customer or supplier
|
||||
frm.set_intro(null);
|
||||
frm.trigger('account_type');
|
||||
|
||||
// show / hide convert buttons
|
||||
frm.trigger('add_toolbar_buttons');
|
||||
}
|
||||
|
||||
if(!frm.doc.__islocal) {
|
||||
// show / hide convert buttons
|
||||
frm.trigger('add_toolbar_buttons');
|
||||
}
|
||||
frm.add_custom_button(__('Update Account Number'), function () {
|
||||
frm.trigger("update_account_number");
|
||||
});
|
||||
|
@ -273,4 +273,8 @@ def update_account_number(name, account_number):
|
||||
def get_name_with_number(new_account, account_number):
|
||||
if account_number and not new_account[0].isdigit():
|
||||
new_account = account_number + " - " + new_account
|
||||
return new_account
|
||||
return new_account
|
||||
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Account", ["lft", "rgt"])
|
@ -101,7 +101,7 @@ def _make_test_records(verbose):
|
||||
def get_inventory_account(company, warehouse=None):
|
||||
account = None
|
||||
if warehouse:
|
||||
account = get_warehouse_account(warehouse, company)
|
||||
account = get_warehouse_account(frappe.get_doc("Warehouse", warehouse))
|
||||
else:
|
||||
account = get_company_default_inventory_account(company)
|
||||
|
||||
|
@ -64,3 +64,6 @@ class CostCenter(NestedSet):
|
||||
if not merge:
|
||||
frappe.db.set_value("Cost Center", newdn, "cost_center_name",
|
||||
" - ".join(newdn.split(" - ")[:-1]))
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Cost Center", ["lft", "rgt"])
|
@ -48,5 +48,10 @@ frappe.treeview_settings["Cost Center"] = {
|
||||
}, __('Budget'));
|
||||
|
||||
},
|
||||
onrender: function(node) {
|
||||
if(node.is_root){
|
||||
node.hide_add = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -769,6 +769,8 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
||||
party_account = doc.receivable_account
|
||||
elif dt == "Employee Advance":
|
||||
party_account = doc.advance_account
|
||||
elif dt == "Expense Claim":
|
||||
party_account = doc.payable_account
|
||||
else:
|
||||
party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company)
|
||||
|
||||
|
@ -1302,10 +1302,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
}
|
||||
});
|
||||
|
||||
if (field == 'qty') {
|
||||
this.remove_zero_qty_item();
|
||||
}
|
||||
|
||||
this.update_paid_amount_status(false)
|
||||
},
|
||||
|
||||
|
@ -2,9 +2,8 @@
|
||||
<style>
|
||||
@media screen {
|
||||
.print-format {
|
||||
padding: 8mm;
|
||||
margin:4mm;
|
||||
font-size: 10.0pt !important;
|
||||
padding: 4mm;
|
||||
font-size: 8.0pt !important;
|
||||
font-family: Tahoma, sans-serif;
|
||||
}
|
||||
}
|
||||
@ -12,9 +11,8 @@
|
||||
{% } %}
|
||||
<style>
|
||||
.print-format {
|
||||
padding: 8mm;
|
||||
margin:4mm;
|
||||
font-size: 10.0pt !important;
|
||||
padding: 4mm;
|
||||
font-size: 8.0pt !important;
|
||||
font-family: Tahoma, sans-serif;
|
||||
}
|
||||
</style>
|
||||
@ -41,7 +39,7 @@
|
||||
var range4 = report.columns[14].label;
|
||||
%}
|
||||
{% if(balance_row) { %}
|
||||
<table class="table table-bordered table-condensed table-sm small">
|
||||
<table class="table table-bordered table-condensed">
|
||||
<caption class="text-right">(Amount in {%= data[0][__("currency")] || "" %})</caption>
|
||||
<colgroup>
|
||||
<col style="width: 30mm;">
|
||||
@ -100,8 +98,8 @@
|
||||
<thead>
|
||||
<tr>
|
||||
{% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
|
||||
<th style="width: 15%">{%= __("Date") %}</th>
|
||||
<th style="width: 20%">{%= __("Reference") %}</th>
|
||||
<th style="width: 18%">{%= __("Date") %}</th>
|
||||
<th style="width: 17%">{%= __("Reference") %}</th>
|
||||
{% if(!filters.show_pdc_in_print) { %}
|
||||
<th style="width: 20%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
|
||||
{% } %}
|
||||
@ -234,4 +232,4 @@
|
||||
{% } %}
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="text-right text-muted">{{ __("Printed On") }}{%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
|
||||
<p class="text-right text-muted">{{ __("Printed On ") }}{%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
|
@ -297,8 +297,7 @@ def filter_accounts(accounts, depth=10):
|
||||
def add_to_list(parent, level):
|
||||
if level < depth:
|
||||
children = parent_children_map.get(parent) or []
|
||||
if parent == None:
|
||||
sort_root_accounts(children)
|
||||
sort_accounts(children, is_root=True if parent==None else False)
|
||||
|
||||
for child in children:
|
||||
child.indent = level
|
||||
@ -310,25 +309,26 @@ def filter_accounts(accounts, depth=10):
|
||||
return filtered_accounts, accounts_by_name, parent_children_map
|
||||
|
||||
|
||||
def sort_root_accounts(roots):
|
||||
def sort_accounts(accounts, is_root=False, key="name"):
|
||||
"""Sort root types as Asset, Liability, Equity, Income, Expense"""
|
||||
|
||||
def compare_roots(a, b):
|
||||
if a.value and re.split('\W+', a.value)[0].isdigit():
|
||||
# if chart of accounts is numbered, then sort by number
|
||||
return cmp(a.value, b.value)
|
||||
if a.report_type != b.report_type and a.report_type == "Balance Sheet":
|
||||
return -1
|
||||
if a.root_type != b.root_type and a.root_type == "Asset":
|
||||
return -1
|
||||
if a.root_type == "Liability" and b.root_type == "Equity":
|
||||
return -1
|
||||
if a.root_type == "Income" and b.root_type == "Expense":
|
||||
return -1
|
||||
def compare_accounts(a, b):
|
||||
if is_root:
|
||||
if a.report_type != b.report_type and a.report_type == "Balance Sheet":
|
||||
return -1
|
||||
if a.root_type != b.root_type and a.root_type == "Asset":
|
||||
return -1
|
||||
if a.root_type == "Liability" and b.root_type == "Equity":
|
||||
return -1
|
||||
if a.root_type == "Income" and b.root_type == "Expense":
|
||||
return -1
|
||||
else:
|
||||
if re.split('\W+', a[key])[0].isdigit():
|
||||
# if chart of accounts is numbered, then sort by number
|
||||
return cmp(a[key], b[key])
|
||||
return 1
|
||||
|
||||
roots.sort(key = functools.cmp_to_key(compare_roots))
|
||||
|
||||
accounts.sort(key = functools.cmp_to_key(compare_accounts))
|
||||
|
||||
def set_gl_entries_by_account(
|
||||
company, from_date, to_date, root_lft, root_rgt, filters, gl_entries_by_account, ignore_closing_entries=False):
|
||||
|
@ -252,16 +252,11 @@ def add_ac(args=None):
|
||||
if not ac.parent_account:
|
||||
ac.parent_account = args.get("parent")
|
||||
|
||||
if getattr(ac, 'is_root', None):
|
||||
ac.parent_account=''
|
||||
|
||||
ac.old_parent = ""
|
||||
ac.freeze_account = "No"
|
||||
if cint(ac.get("is_root")):
|
||||
ac.parent_account = None
|
||||
ac.flags.ignore_mandatory = True
|
||||
else:
|
||||
ac.root_type = None
|
||||
|
||||
ac.insert()
|
||||
|
||||
@ -663,7 +658,7 @@ def get_companies():
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent, company, is_root=False):
|
||||
from erpnext.accounts.report.financial_statements import sort_root_accounts
|
||||
from erpnext.accounts.report.financial_statements import sort_accounts
|
||||
|
||||
fieldname = frappe.db.escape(doctype.lower().replace(' ','_'))
|
||||
doctype = frappe.db.escape(doctype)
|
||||
@ -678,9 +673,6 @@ def get_children(doctype, parent, company, is_root=False):
|
||||
and `company` = %s and docstatus<2
|
||||
order by name""".format(fields=fields, fieldname = fieldname, doctype=doctype),
|
||||
company, as_dict=1)
|
||||
|
||||
if parent=="Accounts":
|
||||
sort_root_accounts(acc)
|
||||
else:
|
||||
# other
|
||||
fields = ", account_currency" if doctype=="Account" else ""
|
||||
@ -693,6 +685,7 @@ def get_children(doctype, parent, company, is_root=False):
|
||||
parent, as_dict=1)
|
||||
|
||||
if doctype == 'Account':
|
||||
sort_accounts(acc, is_root, key="value")
|
||||
company_currency = frappe.db.get_value("Company", company, "default_currency")
|
||||
for each in acc:
|
||||
each["company_currency"] = company_currency
|
||||
|
@ -177,4 +177,7 @@ def get_children(doctype, parent, is_root=False):
|
||||
|
||||
# return nodes
|
||||
return land_units
|
||||
|
||||
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Land Unit", ["lft", "rgt"])
|
@ -15,8 +15,8 @@ frappe.ui.form.on('Soil Texture', {
|
||||
},
|
||||
onload: function(frm) {
|
||||
if (frm.doc.soil_texture_criteria == undefined) frm.call('load_contents');
|
||||
if (this.ternary_plot) return;
|
||||
this.ternary_plot = new agriculture.TernaryPlot({
|
||||
if (frm.doc.ternary_plot) return;
|
||||
frm.doc.ternary_plot = new agriculture.TernaryPlot({
|
||||
parent: frm.get_field("ternary_plot").$wrapper,
|
||||
clay: frm.doc.clay_composition,
|
||||
sand: frm.doc.sand_composition,
|
||||
|
@ -270,6 +270,40 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "company",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -367,6 +401,70 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.docstatus===1",
|
||||
"fieldname": "order_confirmation_no",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Order Confirmation No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.order_confirmation_no",
|
||||
"fieldname": "order_confirmation_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Order Confirmation Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -400,40 +498,6 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "company",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -3258,6 +3322,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -3495,7 +3560,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-02-21 14:26:17.099336",
|
||||
"modified": "2018-03-28 14:09:02.393746",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
@ -336,7 +336,7 @@ def get_data():
|
||||
"color": "#009248",
|
||||
"icon": "/assets/erpnext/images/hub_logo.svg",
|
||||
"type": "page",
|
||||
"link": "Hub/Home",
|
||||
"link": "Hub/Item",
|
||||
"label": _("Hub")
|
||||
},
|
||||
{
|
||||
|
@ -18,5 +18,14 @@ def get_data():
|
||||
"description": _("GoCardless SEPA Mandate"),
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Settings"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Woocommerce Settings"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -667,7 +667,9 @@ class AccountsController(TransactionBase):
|
||||
self.remove(item)
|
||||
|
||||
def set_payment_schedule(self):
|
||||
if self.doctype == 'Sales Invoice' and self.is_pos: return
|
||||
if self.doctype == 'Sales Invoice' and self.is_pos:
|
||||
self.payment_terms_template = ''
|
||||
return
|
||||
|
||||
posting_date = self.get("bill_date") or self.get("posting_date") or self.get("transaction_date")
|
||||
date = self.get("due_date")
|
||||
|
@ -152,6 +152,11 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
|
||||
conditions = []
|
||||
|
||||
description_cond = ''
|
||||
if frappe.db.count('Item', cache=True) < 50000:
|
||||
# scan description only if items are less than 50000
|
||||
description_cond = 'or tabItem.description LIKE %(txt)s'
|
||||
|
||||
return frappe.db.sql("""select tabItem.name, tabItem.item_group,
|
||||
if(length(tabItem.item_name) > 40,
|
||||
concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name,
|
||||
@ -165,8 +170,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
and (tabItem.`{key}` LIKE %(txt)s
|
||||
or tabItem.item_group LIKE %(txt)s
|
||||
or tabItem.item_name LIKE %(txt)s
|
||||
or tabItem.description LIKE %(txt)s)
|
||||
or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
|
||||
or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s
|
||||
{description_cond}))
|
||||
{fcond} {mcond}
|
||||
order by
|
||||
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
||||
@ -176,7 +181,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
limit %(start)s, %(page_len)s """.format(
|
||||
key=searchfield,
|
||||
fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
|
||||
mcond=get_match_cond(doctype).replace('%', '%%')),
|
||||
mcond=get_match_cond(doctype).replace('%', '%%'),
|
||||
description_cond = description_cond),
|
||||
{
|
||||
"today": nowdate(),
|
||||
"txt": "%%%s%%" % txt,
|
||||
|
@ -34,14 +34,14 @@ def work():
|
||||
payroll_entry.salary_slip_based_on_timesheet = 0
|
||||
payroll_entry.create_salary_slips()
|
||||
payroll_entry.submit_salary_slips()
|
||||
payroll_entry.make_accural_jv_entry()
|
||||
payroll_entry.make_accrual_jv_entry()
|
||||
# payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
|
||||
# reference_number=random_string(10))
|
||||
|
||||
payroll_entry.salary_slip_based_on_timesheet = 1
|
||||
payroll_entry.create_salary_slips()
|
||||
payroll_entry.submit_salary_slips()
|
||||
payroll_entry.make_accural_jv_entry()
|
||||
payroll_entry.make_accrual_jv_entry()
|
||||
# payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
|
||||
# reference_number=random_string(10))
|
||||
|
||||
|
Before Width: | Height: | Size: 173 KiB After Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 140 KiB |
After Width: | Height: | Size: 8.7 MiB |
After Width: | Height: | Size: 2.7 MiB |
BIN
erpnext/docs/assets/img/setup/data-export/data-export-tool.gif
Normal file
After Width: | Height: | Size: 2.7 MiB |
@ -0,0 +1,57 @@
|
||||
|
||||
# WooCommerce Integration
|
||||
|
||||
#### Setting Up WooCommerce on ERPNEXT:-
|
||||
|
||||
Steps:-
|
||||
|
||||
1. From Awesome-bar, go to "Woocommerce Settings" doctype.
|
||||
|
||||
2. From your woocommerce site, generate "API consumer key" and "API consumer secret" using Keys/Apps tab.
|
||||
|
||||
3. Paste those generated "API consumer key" and "API consumer secret" into "Woocommerce Settings" doctype.
|
||||
|
||||
4. In "Woocommerce Server URL" paste the url of your site where ERPNEXT is installed.
|
||||
|
||||
5. Make sure "Enable Sync" is checked.
|
||||
|
||||
6. Select Account type from Account Details Section.
|
||||
|
||||
7. Click Save.
|
||||
|
||||
8. After saving, "Secret" and "Endpoint" are generated automatically and can be seen on "Woocommerce Settings" doctype.
|
||||
|
||||
9. Now from your woocommerce site, click on webhooks option and click on "Add Webhook".
|
||||
|
||||
10. Give name to the webhook of your choice. Click on Status dropdown and select "Active". Select Topic as "Order Created". Copy the "Endpoint" from "Woocommerce Settings" doctype and paste it in "Delivery URL" field. Copy "Secret" from "Woocommerce Settings" doctype and paste it in "Secret" field. Keep API VERSION as it is and click on Save Webhook.
|
||||
|
||||
11. Now the WooCommerce is successful setup on your system.
|
||||
|
||||
<img class="screenshot" alt="Woocommerce Integration" src="{{docs_base_url}}/assets/img/erpnext_integrations/woocommerce_setting_config.gif">
|
||||
|
||||
|
||||
### Note:- In above gif, inplace of delivery url on woocommerce website, you need to paste the url you will obtain after saving the "Woocommerce Settings" page (i.e. Endpoint from "Woocommerce Settings"). I pasted other url because I was using localhost. Please paste your endpoint in place of Delivery URL.
|
||||
|
||||
|
||||
|
||||
#### WooCommerce Integration Working:-
|
||||
|
||||
Steps:-
|
||||
|
||||
1. From your Woocommerce website, register yourself as a user.
|
||||
|
||||
2. Now Click on Address Details and provide the required details.
|
||||
|
||||
3. For start shopping, click on Shop option and now available products can be seen.
|
||||
|
||||
4. Add the desired products into cart and click on View Cart.
|
||||
|
||||
5. From Cart, once you have added the desired products, you can click on proceed to checkout.
|
||||
|
||||
6. All billing details and Order details can be seen now. Once you are ok with it, click on Place Order button.
|
||||
|
||||
7. "Order Received" message can been seen indicating that the order is placed successfully.
|
||||
|
||||
8. Now on system where ERPNEXT is installed check the following doctypes: Customer, Address, Item, Sales Order.
|
||||
|
||||
<img class="screenshot" alt="Woocommerce Integration" src="{{docs_base_url}}/assets/img/erpnext_integrations/woocommerce_demo.gif">
|
@ -0,0 +1,32 @@
|
||||
# Data Export Tool
|
||||
|
||||
Use this tool to export data in Excel or CSV format
|
||||
|
||||
To open the Data Export Tool, you can either go to Setup > Data Export OR simply type `Data Export` in Global Search.
|
||||
|
||||
<img alt="Data Export" class="screenshot" src="{{docs_base_url}}/assets/img/setup/data-export/data-export-tool.gif">
|
||||
|
||||
### Options
|
||||
|
||||
1. Select Doctype
|
||||
|
||||
You will be provided with the list of document types which you can export. Scroll through the list or type the name of the Doctype you want to export.
|
||||
|
||||
2. File Type
|
||||
|
||||
Select File format of the data to be exported (Excel or CSV).
|
||||
|
||||
3. Add Filter (optional)
|
||||
|
||||
Add filters to export only required data.
|
||||
This filter is similar to the filter in list view.
|
||||
|
||||
eg. If you want the data of project related to specific company, you can use the filter to select the company.
|
||||
|
||||
4. Field Multicheck (optional)
|
||||
|
||||
Only checked fields will be exported.
|
||||
|
||||
**Note:**
|
||||
|
||||
If you do not want a child table to be exported simply deselect all the fields of that child table.
|
@ -24,7 +24,7 @@ In the document, you can select multiple Purchase Receipts and fetch all items f
|
||||
|
||||
<img class="screenshot" alt="Landed Cost Vouher" src="{{docs_base_url}}/assets/img/stock/landed-cost.png">
|
||||
|
||||
### What happend on submission?
|
||||
### What happens on submission?
|
||||
|
||||
1. On submission of Landed Cost Voucher, the applicable landed cost charges are updated in Purchase Receipt Item table.
|
||||
|
||||
|
@ -8,5 +8,4 @@ bulk-rename
|
||||
renaming-documents
|
||||
search-filter
|
||||
tree-master-renaming
|
||||
pos-view
|
||||
letter-head-in-the-report
|
||||
letter-head-in-the-report
|
||||
|
@ -1,11 +0,0 @@
|
||||
#POS View
|
||||
|
||||
POS (point of sale) view renders form in a different layout, optimized for the quick selection of items. This view has primarily been designed for the retail business.
|
||||
|
||||
Using POS View, you can only create Sales Invoice, without switching to standard form view. For other transactions, like Sales Order, Delivery Note, Purchase Order, Purchase Receipt etc., POS View is only used for Item selection. For entering other values in the transaction, you should switch to form view.
|
||||
|
||||
<img alt="POS View" class="screenshot" src="{{docs_base_url}}/assets/img/articles/pos-view.gif">
|
||||
|
||||
For creating POS Invoice, check following help video.
|
||||
|
||||
<iframe width="660" height="371" src="https://www.youtube.com/embed/4WkelWkbP_c" frameborder="0" allowfullscreen></iframe>
|
@ -26,7 +26,7 @@ class ProgramEnrollmentTool(Document):
|
||||
elif self.get_students_from == "Program Enrollment":
|
||||
condition2 = 'and student_batch_name=%(student_batch)s' if self.student_batch else " "
|
||||
students = frappe.db.sql('''select student, student_name, student_batch_name from `tabProgram Enrollment`
|
||||
where program=%(program)s and academic_year=%(academic_year)s {0} {1}'''
|
||||
where program=%(program)s and academic_year=%(academic_year)s {0} {1} and docstatus != 2'''
|
||||
.format(condition, condition2), self.as_dict(), as_dict=1)
|
||||
|
||||
student_list = [d.student for d in students]
|
||||
|
@ -0,0 +1,206 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, base64, hashlib, hmac, json
|
||||
import datetime
|
||||
from frappe import _
|
||||
|
||||
|
||||
def verify_request():
|
||||
woocommerce_settings = frappe.get_doc("Woocommerce Settings")
|
||||
sig = base64.b64encode(
|
||||
hmac.new(
|
||||
woocommerce_settings.secret.encode('utf8'),
|
||||
frappe.request.data,
|
||||
hashlib.sha256
|
||||
).digest()
|
||||
)
|
||||
|
||||
if frappe.request.data and \
|
||||
frappe.get_request_header("X-Wc-Webhook-Signature") and \
|
||||
not sig == bytes(frappe.get_request_header("X-Wc-Webhook-Signature").encode()):
|
||||
frappe.throw(_("Unverified Webhook Data"))
|
||||
frappe.set_user(woocommerce_settings.modified_by)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def order():
|
||||
|
||||
verify_request()
|
||||
|
||||
if frappe.request.data:
|
||||
fd = json.loads(frappe.request.data)
|
||||
else:
|
||||
return "success"
|
||||
|
||||
event = frappe.get_request_header("X-Wc-Webhook-Event")
|
||||
|
||||
if event == "created":
|
||||
|
||||
raw_billing_data = fd.get("billing")
|
||||
customer_woo_com_email = raw_billing_data.get("email")
|
||||
|
||||
if frappe.get_value("Customer",{"woocommerce_email": customer_woo_com_email}):
|
||||
# Edit
|
||||
link_customer_and_address(raw_billing_data,1)
|
||||
else:
|
||||
# Create
|
||||
link_customer_and_address(raw_billing_data,0)
|
||||
|
||||
|
||||
items_list = fd.get("line_items")
|
||||
for item in items_list:
|
||||
|
||||
item_woo_com_id = item.get("product_id")
|
||||
|
||||
if frappe.get_value("Item",{"woocommerce_id": item_woo_com_id}):
|
||||
#Edit
|
||||
link_item(item,1)
|
||||
else:
|
||||
link_item(item,0)
|
||||
|
||||
|
||||
customer_name = raw_billing_data.get("first_name") + " " + raw_billing_data.get("last_name")
|
||||
|
||||
new_sales_order = frappe.new_doc("Sales Order")
|
||||
new_sales_order.customer = customer_name
|
||||
|
||||
created_date = fd.get("date_created").split("T")
|
||||
new_sales_order.transaction_date = created_date[0]
|
||||
|
||||
new_sales_order.po_no = fd.get("id")
|
||||
new_sales_order.woocommerce_id = fd.get("id")
|
||||
new_sales_order.naming_series = "SO-"
|
||||
|
||||
placed_order_date = created_date[0]
|
||||
raw_date = datetime.datetime.strptime(placed_order_date, "%Y-%m-%d")
|
||||
raw_delivery_date = frappe.utils.add_to_date(raw_date,days = 7)
|
||||
order_delivery_date_str = raw_delivery_date.strftime('%Y-%m-%d')
|
||||
order_delivery_date = str(order_delivery_date_str)
|
||||
|
||||
new_sales_order.delivery_date = order_delivery_date
|
||||
|
||||
for item in items_list:
|
||||
woocomm_item_id = item.get("product_id")
|
||||
found_item = frappe.get_doc("Item",{"woocommerce_id": woocomm_item_id})
|
||||
|
||||
ordered_items_tax = item.get("total_tax")
|
||||
|
||||
default_set_company = frappe.get_doc("Global Defaults")
|
||||
company = default_set_company.default_company
|
||||
found_company = frappe.get_doc("Company",{"name":company})
|
||||
company_abbr = found_company.abbr
|
||||
|
||||
new_sales_order.append("items",{
|
||||
"item_code": found_item.item_code,
|
||||
"item_name": found_item.item_name,
|
||||
"description": found_item.item_name,
|
||||
"delivery_date":order_delivery_date,
|
||||
"uom": "Nos",
|
||||
"qty": item.get("quantity"),
|
||||
"rate": item.get("price"),
|
||||
"warehouse": "Stores" + " - " + company_abbr
|
||||
})
|
||||
|
||||
add_tax_details(new_sales_order,ordered_items_tax,"Ordered Item tax",0)
|
||||
|
||||
# shipping_details = fd.get("shipping_lines") # used for detailed order
|
||||
shipping_total = fd.get("shipping_total")
|
||||
shipping_tax = fd.get("shipping_tax")
|
||||
|
||||
add_tax_details(new_sales_order,shipping_tax,"Shipping Tax",1)
|
||||
add_tax_details(new_sales_order,shipping_total,"Shipping Total",1)
|
||||
|
||||
new_sales_order.submit()
|
||||
|
||||
frappe.db.commit()
|
||||
|
||||
def link_customer_and_address(raw_billing_data,customer_status):
|
||||
|
||||
if customer_status == 0:
|
||||
# create
|
||||
customer = frappe.new_doc("Customer")
|
||||
address = frappe.new_doc("Address")
|
||||
|
||||
if customer_status == 1:
|
||||
# Edit
|
||||
customer_woo_com_email = raw_billing_data.get("email")
|
||||
customer = frappe.get_doc("Customer",{"woocommerce_email": customer_woo_com_email})
|
||||
old_name = customer.customer_name
|
||||
|
||||
full_name = str(raw_billing_data.get("first_name"))+ " "+str(raw_billing_data.get("last_name"))
|
||||
customer.customer_name = full_name
|
||||
customer.woocommerce_email = str(raw_billing_data.get("email"))
|
||||
customer.save()
|
||||
frappe.db.commit()
|
||||
|
||||
if customer_status == 1:
|
||||
frappe.rename_doc("Customer", old_name, full_name)
|
||||
address = frappe.get_doc("Address",{"woocommerce_email":customer_woo_com_email})
|
||||
customer = frappe.get_doc("Customer",{"woocommerce_email": customer_woo_com_email})
|
||||
|
||||
address.address_line1 = raw_billing_data.get("address_1", "Not Provided")
|
||||
address.address_line2 = raw_billing_data.get("address_2", "Not Provided")
|
||||
address.city = raw_billing_data.get("city", "Not Provided")
|
||||
address.woocommerce_email = str(raw_billing_data.get("email"))
|
||||
address.address_type = "Shipping"
|
||||
address.country = frappe.get_value("Country", filters={"code":raw_billing_data.get("country", "IN").lower()})
|
||||
address.state = raw_billing_data.get("state")
|
||||
address.pincode = str(raw_billing_data.get("postcode"))
|
||||
address.phone = str(raw_billing_data.get("phone"))
|
||||
address.email_id = str(raw_billing_data.get("email"))
|
||||
|
||||
address.append("links", {
|
||||
"link_doctype": "Customer",
|
||||
"link_name": customer.customer_name
|
||||
})
|
||||
|
||||
address.save()
|
||||
frappe.db.commit()
|
||||
|
||||
if customer_status == 1:
|
||||
|
||||
address = frappe.get_doc("Address",{"woocommerce_email":customer_woo_com_email})
|
||||
old_address_title = address.name
|
||||
new_address_title = customer.customer_name+"-billing"
|
||||
address.address_title = customer.customer_name
|
||||
address.save()
|
||||
|
||||
frappe.rename_doc("Address",old_address_title,new_address_title)
|
||||
|
||||
frappe.db.commit()
|
||||
|
||||
def link_item(item_data,item_status):
|
||||
|
||||
if item_status == 0:
|
||||
#Create Item
|
||||
item = frappe.new_doc("Item")
|
||||
|
||||
if item_status == 1:
|
||||
#Edit Item
|
||||
item_woo_com_id = item_data.get("product_id")
|
||||
item = frappe.get_doc("Item",{"woocommerce_id": item_woo_com_id})
|
||||
|
||||
item.item_name = str(item_data.get("name"))
|
||||
item.item_code = "woocommerce - " + str(item_data.get("product_id"))
|
||||
item.woocommerce_id = str(item_data.get("product_id"))
|
||||
item.item_group = "WooCommerce Products"
|
||||
item.save()
|
||||
frappe.db.commit()
|
||||
|
||||
def add_tax_details(sales_order,price,desc,status):
|
||||
|
||||
woocommerce_settings = frappe.get_doc("Woocommerce Settings")
|
||||
|
||||
if status == 0:
|
||||
# Product taxes
|
||||
account_head_type = woocommerce_settings.tax_account
|
||||
|
||||
if status == 1:
|
||||
# Shipping taxes
|
||||
account_head_type = woocommerce_settings.f_n_f_account
|
||||
|
||||
sales_order.append("taxes",{
|
||||
"charge_type":"Actual",
|
||||
"account_head": account_head_type,
|
||||
"tax_amount": price,
|
||||
"description": desc
|
||||
})
|
@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Woocommerce Settings", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Woocommerce Settings
|
||||
() => frappe.tests.make('Woocommerce Settings', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -0,0 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
|
||||
class TestWoocommerceSettings(unittest.TestCase):
|
||||
pass
|
@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Woocommerce Settings', {
|
||||
refresh (frm) {
|
||||
frm.trigger("add_button_generate_secret");
|
||||
frm.trigger("check_enabled");
|
||||
frm.set_query("tax_account", ()=>{
|
||||
return {
|
||||
"filters": {
|
||||
"company": frappe.defaults.get_default("company"),
|
||||
"is_group": 0
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
enable_sync (frm) {
|
||||
frm.trigger("check_enabled");
|
||||
},
|
||||
|
||||
add_button_generate_secret(frm) {
|
||||
frm.add_custom_button(__('Generate Secret'), () => {
|
||||
frappe.confirm(
|
||||
__("Apps using current key won't be able to access, are you sure?"),
|
||||
() => {
|
||||
frappe.call({
|
||||
type:"POST",
|
||||
method:"erpnext.erpnext_integrations.doctype.woocommerce_settings.woocommerce_settings.generate_secret",
|
||||
}).done(() => {
|
||||
frm.reload_doc();
|
||||
}).fail(() => {
|
||||
frappe.msgprint(__("Could not generate Secret"));
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
check_enabled (frm) {
|
||||
frm.set_df_property("woocommerce_server_url", "reqd", frm.doc.enable_sync);
|
||||
frm.set_df_property("api_consumer_key", "reqd", frm.doc.enable_sync);
|
||||
frm.set_df_property("api_consumer_secret", "reqd", frm.doc.enable_sync);
|
||||
}
|
||||
});
|
@ -0,0 +1,465 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-02-12 15:10:05.495713",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "enable_sync",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Enable Sync",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sb_00",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "woocommerce_server_url",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Woocommerce Server URL",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "secret",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Secret",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cb_00",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "api_consumer_key",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "API consumer key",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "api_consumer_secret",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "API consumer secret",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fieldname": "sb_accounting_details",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Accounting Details",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "tax_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Tax Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_10",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "f_n_f_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Freight and Forwarding Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fieldname": "endpoints",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Endpoints",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "endpoint",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Endpoint",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-03-23 16:57:20.880513",
|
||||
"modified_by": "Administrator",
|
||||
"module": "ERPNext Integrations",
|
||||
"name": "Woocommerce Settings",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from six.moves.urllib.parse import urlparse
|
||||
|
||||
class WoocommerceSettings(Document):
|
||||
def validate(self):
|
||||
self.validate_settings()
|
||||
self.create_delete_custom_fields()
|
||||
self.create_webhook_url()
|
||||
|
||||
def create_delete_custom_fields(self):
|
||||
if self.enable_sync:
|
||||
# create
|
||||
create_custom_field_id_and_check_status = False
|
||||
create_custom_field_email_check = False
|
||||
names = ["Customer-woocommerce_id","Sales Order-woocommerce_id","Item-woocommerce_id","Address-woocommerce_id"]
|
||||
names_check_box = ["Customer-woocommerce_check","Sales Order-woocommerce_check","Item-woocommerce_check","Address-woocommerce_check"]
|
||||
email_names = ["Customer-woocommerce_email","Address-woocommerce_email"]
|
||||
|
||||
for i in zip(names,names_check_box):
|
||||
|
||||
if not frappe.get_value("Custom Field",{"name":i[0]}) or not frappe.get_value("Custom Field",{"name":i[1]}):
|
||||
create_custom_field_id_and_check_status = True
|
||||
break;
|
||||
|
||||
|
||||
if create_custom_field_id_and_check_status:
|
||||
names = ["Customer","Sales Order","Item","Address"]
|
||||
for name in names:
|
||||
custom = frappe.new_doc("Custom Field")
|
||||
custom.dt = name
|
||||
custom.label = "woocommerce_id"
|
||||
custom.read_only = 1
|
||||
custom.save()
|
||||
|
||||
custom = frappe.new_doc("Custom Field")
|
||||
custom.dt = name
|
||||
custom.label = "woocommerce_check"
|
||||
custom.fieldtype = "Check"
|
||||
custom.read_only = 1
|
||||
custom.save()
|
||||
|
||||
for i in email_names:
|
||||
|
||||
if not frappe.get_value("Custom Field",{"name":i}):
|
||||
create_custom_field_email_check = True
|
||||
break;
|
||||
|
||||
if create_custom_field_email_check:
|
||||
names = ["Customer","Address"]
|
||||
for name in names:
|
||||
custom = frappe.new_doc("Custom Field")
|
||||
custom.dt = name
|
||||
custom.label = "woocommerce_email"
|
||||
custom.read_only = 1
|
||||
custom.save()
|
||||
|
||||
if not frappe.get_value("Item Group",{"name": "WooCommerce Products"}):
|
||||
item_group = frappe.new_doc("Item Group")
|
||||
item_group.item_group_name = "WooCommerce Products"
|
||||
item_group.parent_item_group = "All Item Groups"
|
||||
item_group.save()
|
||||
|
||||
|
||||
elif not self.enable_sync:
|
||||
# delete
|
||||
names = ["Customer-woocommerce_id","Sales Order-woocommerce_id","Item-woocommerce_id","Address-woocommerce_id"]
|
||||
names_check_box = ["Customer-woocommerce_check","Sales Order-woocommerce_check","Item-woocommerce_check","Address-woocommerce_check"]
|
||||
email_names = ["Customer-woocommerce_email","Address-woocommerce_email"]
|
||||
for name in names:
|
||||
frappe.delete_doc("Custom Field",name)
|
||||
|
||||
for name in names_check_box:
|
||||
frappe.delete_doc("Custom Field",name)
|
||||
|
||||
for name in email_names:
|
||||
frappe.delete_doc("Custom Field",name)
|
||||
|
||||
frappe.delete_doc("Item Group","WooCommerce Products")
|
||||
|
||||
frappe.db.commit()
|
||||
|
||||
def validate_settings(self):
|
||||
if self.enable_sync:
|
||||
if not self.secret:
|
||||
self.set("secret", frappe.generate_hash())
|
||||
|
||||
if not self.woocommerce_server_url:
|
||||
frappe.throw(_("Please enter Woocommerce Server URL"))
|
||||
|
||||
if not self.api_consumer_key:
|
||||
frappe.throw(_("Please enter API Consumer Key"))
|
||||
|
||||
if not self.api_consumer_secret:
|
||||
frappe.throw(_("Please enter API Consumer Secret"))
|
||||
|
||||
def create_webhook_url(self):
|
||||
endpoint = "/api/method/erpnext.erpnext_integrations.connectors.woocommerce_connection.order"
|
||||
|
||||
try:
|
||||
url = frappe.request.url
|
||||
except RuntimeError:
|
||||
# for CI Test to work
|
||||
url = "http://localhost:8000"
|
||||
|
||||
server_url = '{uri.scheme}://{uri.netloc}'.format(
|
||||
uri=urlparse(url)
|
||||
)
|
||||
|
||||
delivery_url = server_url + endpoint
|
||||
self.endpoint = delivery_url
|
||||
|
||||
@frappe.whitelist()
|
||||
def generate_secret():
|
||||
woocommerce_settings = frappe.get_doc("Woocommerce Settings")
|
||||
woocommerce_settings.secret = frappe.generate_hash()
|
||||
woocommerce_settings.save()
|
@ -42,6 +42,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -73,6 +74,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -104,6 +106,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -135,6 +138,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -165,6 +169,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -196,6 +201,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -227,6 +233,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -257,6 +264,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -287,6 +295,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -318,6 +327,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -347,6 +357,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -378,6 +389,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -409,6 +421,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -439,6 +452,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -469,6 +483,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -482,7 +497,7 @@
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 1,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
@ -500,6 +515,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -531,6 +547,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -563,6 +580,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -594,6 +612,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -625,6 +644,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -656,6 +676,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -686,6 +707,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -715,6 +737,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -745,6 +768,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -774,6 +798,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -805,6 +830,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -836,6 +862,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -865,6 +892,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -895,6 +923,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -924,6 +953,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -954,6 +984,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -983,6 +1014,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1013,6 +1045,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1042,6 +1075,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1072,6 +1106,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1102,6 +1137,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1132,6 +1168,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1162,6 +1199,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1193,6 +1231,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1223,6 +1262,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1253,6 +1293,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1283,6 +1324,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1313,6 +1355,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1343,6 +1386,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1374,6 +1418,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@ -1388,7 +1433,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-22 14:32:27.994634",
|
||||
"modified": "2018-04-05 12:20:25.061368",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Lab Test",
|
||||
@ -1397,7 +1442,6 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
@ -1417,7 +1461,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@ -1437,7 +1480,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
@ -40,6 +40,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -71,6 +72,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -101,6 +103,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -133,6 +136,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -164,6 +168,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -193,6 +198,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -226,6 +232,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -259,6 +266,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -291,6 +299,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -323,6 +332,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -354,6 +364,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -384,6 +395,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -413,6 +425,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -445,6 +458,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -475,6 +489,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -506,6 +521,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -537,6 +553,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -567,6 +584,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -598,6 +616,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -629,6 +648,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -658,6 +678,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -688,6 +709,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -718,6 +740,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -749,6 +772,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -780,6 +804,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -811,6 +836,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -841,6 +867,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -872,6 +899,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -886,7 +914,7 @@
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
@ -903,6 +931,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@ -916,7 +945,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-10-05 12:12:11.918652",
|
||||
"modified": "2018-04-05 12:21:01.837502",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Healthcare",
|
||||
"name": "Lab Test Template",
|
||||
@ -925,7 +954,6 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
@ -945,7 +973,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
@ -12,7 +12,7 @@ def get_data():
|
||||
},
|
||||
{
|
||||
'label': _('Lab Tests and Vital Signs'),
|
||||
'items': ['Lab Test', 'Vital Signs']
|
||||
'items': ['Lab Test', 'Sample Collection', 'Vital Signs']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
18
erpnext/healthcare/doctype/physician/physician_dashboard.py
Normal file
@ -0,0 +1,18 @@
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on transactions against this Physician.'),
|
||||
'fieldname': 'physician',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Appointments and Consultations'),
|
||||
'items': ['Patient Appointment', 'Consultation']
|
||||
},
|
||||
{
|
||||
'label': _('Lab Tests'),
|
||||
'items': ['Lab Test']
|
||||
}
|
||||
]
|
||||
}
|
@ -199,7 +199,6 @@ doc_events = {
|
||||
"validate": "erpnext.portal.doctype.products_settings.products_settings.home_page_is_products"
|
||||
},
|
||||
"Sales Invoice": {
|
||||
'validate': 'erpnext.regional.india.utils.set_place_of_supply',
|
||||
"on_submit": "erpnext.regional.france.utils.create_transaction_log",
|
||||
"on_trash": "erpnext.regional.check_deletion_permission"
|
||||
},
|
||||
@ -210,7 +209,7 @@ doc_events = {
|
||||
'Address': {
|
||||
'validate': 'erpnext.regional.india.utils.validate_gstin_for_india'
|
||||
},
|
||||
'Purchase Invoice': {
|
||||
('Sales Invoice', 'Purchase Invoice', 'Delivery Note'): {
|
||||
'validate': 'erpnext.regional.india.utils.set_place_of_supply'
|
||||
}
|
||||
}
|
||||
|
@ -234,6 +234,40 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"depends_on": "user_id",
|
||||
"description": "This will restrict user access to other employee records",
|
||||
"fieldname": "create_user_permission",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Create User Permission",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -938,40 +972,6 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Provide Email Address registered in company",
|
||||
"fieldname": "company_email",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company Email",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "company_email",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Email",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -1260,6 +1260,36 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cell_number",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Cell Number",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -1331,7 +1361,8 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cell_number",
|
||||
"description": "Provide Email Address registered in company",
|
||||
"fieldname": "company_email",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@ -1340,9 +1371,12 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Cell Number",
|
||||
"label": "Company Email",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "company_email",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Email",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -2668,7 +2702,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-03-09 15:04:16.056386",
|
||||
"modified": "2018-04-05 13:54:36.881449",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee",
|
||||
@ -2677,7 +2711,6 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@ -2697,7 +2730,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
@ -2713,12 +2745,10 @@
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"user_permission_doctypes": "[\"Branch\",\"Company\",\"Department\",\"Designation\"]",
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
|
@ -42,7 +42,7 @@ class Employee(NestedSet):
|
||||
self.validate_status()
|
||||
self.validate_employee_leave_approver()
|
||||
self.validate_reports_to()
|
||||
self.validate_prefered_email()
|
||||
self.validate_preferred_email()
|
||||
|
||||
if self.user_id:
|
||||
self.validate_for_enabled_user_id()
|
||||
@ -63,6 +63,7 @@ class Employee(NestedSet):
|
||||
self.update_user_permissions()
|
||||
|
||||
def update_user_permissions(self):
|
||||
if not self.create_user_permission: return
|
||||
frappe.permissions.add_user_permission("Employee", self.name, self.user_id)
|
||||
frappe.permissions.set_user_permission_if_allowed("Company", self.company, self.user_id)
|
||||
|
||||
@ -162,7 +163,7 @@ class Employee(NestedSet):
|
||||
self.update_nsm_model()
|
||||
delete_events(self.doctype, self.name)
|
||||
|
||||
def validate_prefered_email(self):
|
||||
def validate_preferred_email(self):
|
||||
if self.prefered_contact_email and not self.get(scrub(self.prefered_contact_email)):
|
||||
frappe.msgprint(_("Please enter " + self.prefered_contact_email))
|
||||
|
||||
@ -329,4 +330,8 @@ def get_children(doctype, parent=None, company=None, is_root=False, is_tree=Fals
|
||||
.format(company=company, condition=condition), as_dict=1)
|
||||
|
||||
# return employee
|
||||
return employee
|
||||
return employee
|
||||
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Employee", ["lft", "rgt"])
|
@ -82,9 +82,9 @@ cur_frm.cscript.refresh = function(doc) {
|
||||
if (cint(doc.total_amount_reimbursed) > 0 && frappe.model.can_read(entry_doctype)) {
|
||||
cur_frm.add_custom_button(__('Bank Entries'), function() {
|
||||
frappe.route_options = {
|
||||
entry_route_doctype: me.frm.doc.doctype,
|
||||
entry_route_name: me.frm.doc.name,
|
||||
company: me.frm.doc.company
|
||||
party_type: "Employee",
|
||||
party: doc.employee,
|
||||
company: doc.company
|
||||
};
|
||||
frappe.set_route("List", entry_doctype);
|
||||
}, __("View"));
|
||||
@ -181,7 +181,7 @@ frappe.ui.form.on("Expense Claim", {
|
||||
make_payment_entry: function(frm) {
|
||||
var method = "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry";
|
||||
if(frm.doc.__onload && frm.doc.__onload.make_payment_via_journal_entry) {
|
||||
method = "erpnext.hr.doctype.expense_claim.expense_claim.make_bank_entry"
|
||||
method = "erpnext.hr.doctype.expense_claim.expense_claim.make_bank_entry";
|
||||
}
|
||||
return frappe.call({
|
||||
method: method,
|
||||
|
@ -164,7 +164,7 @@ class PayrollEntry(Document):
|
||||
except frappe.ValidationError:
|
||||
not_submitted_ss.append(ss_dict)
|
||||
if submitted_ss:
|
||||
jv_name = self.make_accural_jv_entry()
|
||||
jv_name = self.make_accrual_jv_entry()
|
||||
frappe.msgprint(_("Salary Slip submitted for period from {0} to {1}")
|
||||
.format(ss_obj.start_date, ss_obj.end_date))
|
||||
|
||||
@ -237,7 +237,7 @@ class PayrollEntry(Document):
|
||||
|
||||
return payroll_payable_account
|
||||
|
||||
def make_accural_jv_entry(self):
|
||||
def make_accrual_jv_entry(self):
|
||||
self.check_permission('write')
|
||||
earnings = self.get_salary_component_total(component_type = "earnings") or {}
|
||||
deductions = self.get_salary_component_total(component_type = "deductions") or {}
|
||||
@ -249,7 +249,7 @@ class PayrollEntry(Document):
|
||||
if earnings or deductions:
|
||||
journal_entry = frappe.new_doc('Journal Entry')
|
||||
journal_entry.voucher_type = 'Journal Entry'
|
||||
journal_entry.user_remark = _('Accural Journal Entry for salaries from {0} to {1}')\
|
||||
journal_entry.user_remark = _('Accrual Journal Entry for salaries from {0} to {1}')\
|
||||
.format(self.start_date, self.end_date)
|
||||
journal_entry.company = self.company
|
||||
journal_entry.posting_date = self.posting_date
|
||||
|
@ -17,6 +17,5 @@ class SalaryComponent(Document):
|
||||
self.salary_component.split()]).upper()
|
||||
|
||||
self.salary_component_abbr = self.salary_component_abbr.strip()
|
||||
|
||||
self.salary_component_abbr = append_number_if_name_exists('Salary Component',
|
||||
self.salary_component_abbr, 'salary_component_abbr', separator='_')
|
||||
self.salary_component_abbr = append_number_if_name_exists('Salary Component', self.salary_component_abbr,
|
||||
'salary_component_abbr', separator='_', filters={"name": ["!=", self.name]})
|
@ -39,6 +39,16 @@ frappe.ui.form.on('Salary Structure', {
|
||||
}
|
||||
}
|
||||
});
|
||||
frm.set_query("payment_account", function () {
|
||||
var account_types = ["Bank", "Cash"];
|
||||
return {
|
||||
filters: {
|
||||
"account_type": ["in", account_types],
|
||||
"is_group": 0,
|
||||
"company": frm.doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
|
@ -22,13 +22,64 @@ def get_list(doctype, start=0, limit=20, fields=["*"], filters="{}", order_by=No
|
||||
response = connection.get_list(doctype,
|
||||
limit_start=start, limit_page_length=limit,
|
||||
filters=filters, fields=fields)
|
||||
return response
|
||||
|
||||
# Bad, need child tables in response
|
||||
listing = []
|
||||
for obj in response:
|
||||
doc = connection.get_doc(doctype, obj['name'])
|
||||
listing.append(doc)
|
||||
|
||||
return listing
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_favourites(start=0, limit=20, fields=["*"], order_by=None):
|
||||
doctype = 'Hub Item'
|
||||
hub_settings = frappe.get_doc('Hub Settings')
|
||||
item_names_str = hub_settings.get('custom_data') or '[]'
|
||||
item_names = json.loads(item_names_str)
|
||||
filters = json.dumps({
|
||||
'hub_item_code': ['in', item_names]
|
||||
})
|
||||
return get_list(doctype, start, limit, fields, filters, order_by)
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_wishlist_item(item_name, remove=0):
|
||||
remove = int(remove)
|
||||
hub_settings = frappe.get_doc('Hub Settings')
|
||||
data = hub_settings.get('custom_data')
|
||||
if not data or not json.loads(data):
|
||||
data = '[]'
|
||||
hub_settings.custom_data = data
|
||||
hub_settings.save()
|
||||
|
||||
item_names_str = data
|
||||
item_names = json.loads(item_names_str)
|
||||
if not remove and item_name not in item_names:
|
||||
item_names.append(item_name)
|
||||
if remove and item_name in item_names:
|
||||
item_names.remove(item_name)
|
||||
|
||||
item_names_str = json.dumps(item_names)
|
||||
|
||||
hub_settings.custom_data = item_names_str
|
||||
hub_settings.save()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_meta(doctype):
|
||||
connection = get_client_connection()
|
||||
meta = connection.get_doc('DocType', doctype)
|
||||
return meta
|
||||
categories = connection.get_list('Hub Category',
|
||||
limit_start=0, limit_page_length=300,
|
||||
filters={}, fields=['name'])
|
||||
|
||||
categories = [d.get('name') for d in categories]
|
||||
return {
|
||||
'meta': meta,
|
||||
'companies': connection.get_list('Hub Company',
|
||||
limit_start=0, limit_page_length=300,
|
||||
filters={}, fields=['name']),
|
||||
'categories': categories
|
||||
}
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_categories(parent='All Categories'):
|
||||
@ -40,12 +91,42 @@ def get_categories(parent='All Categories'):
|
||||
return response
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_category(item_name, category):
|
||||
def update_category(hub_item_code, category):
|
||||
connection = get_hub_connection()
|
||||
response = connection.update('Hub Item', dict(
|
||||
|
||||
# args = frappe._dict(dict(
|
||||
# doctype='Hub Category',
|
||||
# hub_category_name=category
|
||||
# ))
|
||||
# response = connection.insert('Hub Category', args)
|
||||
|
||||
response = connection.update('Hub Item', frappe._dict(dict(
|
||||
doctype='Hub Item',
|
||||
hub_category = category
|
||||
), item_name)
|
||||
return response.ok
|
||||
)), hub_item_code)
|
||||
|
||||
return response
|
||||
|
||||
@frappe.whitelist()
|
||||
def send_review(hub_item_code, review):
|
||||
review = json.loads(review)
|
||||
hub_connection = get_hub_connection()
|
||||
|
||||
item_doc = hub_connection.connection.get_doc('Hub Item', hub_item_code)
|
||||
existing_reviews = item_doc.get('reviews')
|
||||
|
||||
reviews = [review]
|
||||
review.setdefault('idx', 0)
|
||||
for r in existing_reviews:
|
||||
if r.get('user') != review.get('user'):
|
||||
reviews.append(r)
|
||||
|
||||
response = hub_connection.update('Hub Item', dict(
|
||||
doctype='Hub Item',
|
||||
reviews = reviews
|
||||
), hub_item_code)
|
||||
|
||||
return response
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_details(hub_sync_id=None, doctype='Hub Item'):
|
||||
@ -53,6 +134,11 @@ def get_details(hub_sync_id=None, doctype='Hub Item'):
|
||||
return
|
||||
connection = get_client_connection()
|
||||
details = connection.get_doc(doctype, hub_sync_id)
|
||||
reviews = details.get('reviews')
|
||||
if reviews and len(reviews):
|
||||
for r in reviews:
|
||||
r.setdefault('pretty_date', frappe.utils.pretty_date(r.get('modified')))
|
||||
details.setdefault('reviews', reviews)
|
||||
return details
|
||||
|
||||
def get_client_connection():
|
||||
|
@ -4,10 +4,6 @@
|
||||
"doctype": "Data Migration Plan",
|
||||
"idx": 1,
|
||||
"mappings": [
|
||||
{
|
||||
"enabled": 1,
|
||||
"mapping": "Company to Hub Company"
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"mapping": "Item to Hub Item"
|
||||
|
@ -6,20 +6,33 @@ frappe.ui.form.on("Hub Settings", {
|
||||
}));
|
||||
|
||||
frm.trigger("enabled");
|
||||
frm.add_custom_button(__('View Hub'),
|
||||
() => frappe.set_route('Hub', 'Item'));
|
||||
if (frm.doc.enabled) {
|
||||
frm.add_custom_button(__('View Hub'),
|
||||
() => frappe.set_route('hub'));
|
||||
frm.add_custom_button(__('Sync'),
|
||||
() => frm.call('sync'));
|
||||
}
|
||||
},
|
||||
onload: function(frm) {
|
||||
let token = frappe.urllib.get_arg("access_token");
|
||||
if(token) {
|
||||
let email = frm.get_field("user");
|
||||
console.log('token', frappe.urllib.get_arg("access_token"));
|
||||
|
||||
get_user_details(frm, token, email);
|
||||
let row = frappe.model.add_child(frm.doc, "Hub Users", "users");
|
||||
row.user = frappe.session.user;
|
||||
}
|
||||
|
||||
if(!frm.doc.country) {
|
||||
frm.set_value("country", frappe.defaults.get_default("Country"));
|
||||
}
|
||||
if(!frm.doc.company) {
|
||||
frm.set_value("company", frappe.defaults.get_default("Company"));
|
||||
}
|
||||
if(!frm.doc.user) {
|
||||
frm.set_value("user", frappe.session.user);
|
||||
}
|
||||
},
|
||||
onload_post_render: function(frm) {
|
||||
if(frm.get_field("unregister_from_hub").$input)
|
||||
@ -48,33 +61,47 @@ frappe.ui.form.on("Hub Settings", {
|
||||
if(frappe.session.user === "Administrator") {
|
||||
frappe.msgprint(__("Please login as another user."))
|
||||
} else {
|
||||
frappe.verify_password(() => {
|
||||
this.frm.call({
|
||||
doc: this.frm.doc,
|
||||
method: "register",
|
||||
args: {},
|
||||
freeze: true,
|
||||
callback: function(r) {},
|
||||
onerror: function() {
|
||||
frappe.msgprint(__("Wrong Password"));
|
||||
frm.set_value("enabled", 0);
|
||||
}
|
||||
});
|
||||
} );
|
||||
// frappe.verify_password(() => {
|
||||
|
||||
// } );
|
||||
|
||||
frm.trigger("call_pre_reg");
|
||||
// frm.trigger("call_register");
|
||||
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// update_hub: (frm) => {
|
||||
// this.frm.call({
|
||||
// doc: this.frm.doc,
|
||||
// method: "update_hub",
|
||||
// args: {},
|
||||
// freeze: true,
|
||||
// callback: function(r) { },
|
||||
// onerror: function() { }
|
||||
// });
|
||||
// },
|
||||
call_pre_reg: (frm) => {
|
||||
this.frm.call({
|
||||
doc: this.frm.doc,
|
||||
method: "pre_reg",
|
||||
args: {},
|
||||
freeze: true,
|
||||
callback: function(r) {
|
||||
console.log(r.message);
|
||||
authorize(frm, r.message.client_id, r.message.redirect_uri);
|
||||
},
|
||||
onerror: function() {
|
||||
frappe.msgprint(__("Wrong Password"));
|
||||
frm.set_value("enabled", 0);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
call_register: (frm) => {
|
||||
this.frm.call({
|
||||
doc: this.frm.doc,
|
||||
method: "register",
|
||||
args: {},
|
||||
freeze: true,
|
||||
callback: function(r) {},
|
||||
onerror: function() {
|
||||
frappe.msgprint(__("Wrong Password"));
|
||||
frm.set_value("enabled", 0);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
unregister_from_hub: (frm) => {
|
||||
frappe.verify_password(() => {
|
||||
@ -85,3 +112,67 @@ frappe.ui.form.on("Hub Settings", {
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// let hub_url = 'https://hubmarket.org'
|
||||
let hub_url = 'http://159.89.175.122'
|
||||
// let hub_url = 'http://erpnext.hub:8000'
|
||||
|
||||
function authorize(frm, client_id, redirect_uri) {
|
||||
|
||||
// queryStringData is details of OAuth Client (Implicit Grant) on Custom App
|
||||
var queryStringData = {
|
||||
response_type : "token",
|
||||
client_id : client_id,
|
||||
redirect_uri : redirect_uri
|
||||
}
|
||||
|
||||
// Get current raw route and build url
|
||||
const route = "/desk#" + frappe.get_raw_route_str();
|
||||
localStorage.removeItem("route"); // Clear previously set route if any
|
||||
localStorage.setItem("route", route);
|
||||
|
||||
// Go authorize!
|
||||
let api_route = "/api/method/frappe.integrations.oauth2.authorize?";
|
||||
let url = hub_url + api_route + $.param(queryStringData);
|
||||
window.location.replace(url, 'test');
|
||||
}
|
||||
|
||||
function get_user_details(frm, token, email) {
|
||||
console.log('user_details');
|
||||
var route = localStorage.getItem("route");
|
||||
if (token && route) {
|
||||
// Clean up access token from route
|
||||
frappe.set_route(frappe.get_route().join("/"))
|
||||
|
||||
// query protected resource e.g. Hub Items with token
|
||||
var call = {
|
||||
"async": true,
|
||||
"crossDomain": true,
|
||||
"url": hub_url + "/api/resource/User",
|
||||
"method": "GET",
|
||||
"data": {
|
||||
// "email": email,
|
||||
"fields": '["name", "first_name", "language"]',
|
||||
"limit_page_length": 1
|
||||
},
|
||||
"headers": {
|
||||
"authorization": "Bearer " + token,
|
||||
"content-type": "application/x-www-form-urlencoded"
|
||||
}
|
||||
}
|
||||
$.ajax(call).done(function (response) {
|
||||
// display openid profile
|
||||
console.log('response', response);
|
||||
|
||||
let data = response.data[0];
|
||||
frm.set_value("enabled", 1);
|
||||
frm.set_value("hub_username", data.first_name);
|
||||
frm.set_value("hub_user_status", "Starter");
|
||||
frm.set_value("language", data.language);
|
||||
frm.save();
|
||||
|
||||
// clear route from localStorage
|
||||
localStorage.removeItem("route");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -70,6 +71,39 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "enabled",
|
||||
"fieldname": "hub_username",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Hub Username",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -101,6 +135,102 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_0",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "enabled",
|
||||
"fieldname": "hub_user_status",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "enabled",
|
||||
"fieldname": "language",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Language",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -133,6 +263,38 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company_registered",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company Registered",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -164,6 +326,38 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company_email",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company Email",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -195,6 +389,38 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company_logo",
|
||||
"fieldtype": "Attach Image",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company Logo",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -225,6 +451,70 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "users_sb",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Enabled Users",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "users",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Users",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Hub Users",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -256,6 +546,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -286,6 +577,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -317,6 +609,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -349,6 +642,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -380,6 +674,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -411,6 +706,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -418,6 +714,39 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"depends_on": "eval:1",
|
||||
"fieldname": "custom_data",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Custom Data",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "",
|
||||
"columns": 0,
|
||||
"depends_on": "enabled",
|
||||
@ -443,6 +772,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -473,6 +803,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@ -486,8 +817,8 @@
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-09-21 12:13:50.841646",
|
||||
"modified_by": "manas@erpnext.com",
|
||||
"modified": "2018-03-26 00:55:17.929140",
|
||||
"modified_by": "test1@example.com",
|
||||
"module": "Hub Node",
|
||||
"name": "Hub Settings",
|
||||
"name_case": "",
|
||||
|
@ -11,6 +11,21 @@ from erpnext.utilities.product import get_price, get_qty_in_stock
|
||||
from six import string_types
|
||||
|
||||
hub_url = "https://hubmarket.org"
|
||||
# hub_url = "http://159.89.175.122"
|
||||
# hub_url = "http://erpnext.hub:8000"
|
||||
|
||||
class OAuth2Session():
|
||||
def __init__(self, headers):
|
||||
self.headers = headers
|
||||
def get(self, url, params, headers, verify):
|
||||
res = requests.get(url, params=params, headers=self.headers, verify=verify)
|
||||
return res
|
||||
def post(self, url, data, verify):
|
||||
res = requests.post(url, data=data, headers=self.headers, verify=verify)
|
||||
return res
|
||||
def put(self, url, data, verify):
|
||||
res = requests.put(url, data=data, headers=self.headers, verify=verify)
|
||||
return res
|
||||
|
||||
class HubSetupError(frappe.ValidationError): pass
|
||||
|
||||
@ -35,6 +50,33 @@ class HubSettings(Document):
|
||||
|
||||
doc.run()
|
||||
|
||||
def pre_reg(self):
|
||||
site_name = frappe.local.site + ':' + str(frappe.conf.webserver_port)
|
||||
protocol = 'http://'
|
||||
route = '/token'
|
||||
data = {
|
||||
'site_name': site_name,
|
||||
'protocol': protocol,
|
||||
'route': route
|
||||
}
|
||||
|
||||
redirect_url = protocol + site_name + route
|
||||
post_url = hub_url + '/api/method/hub.hub.api.pre_reg'
|
||||
|
||||
response = requests.post(post_url, data=data)
|
||||
response.raise_for_status()
|
||||
message = response.json().get('message')
|
||||
|
||||
if message and message.get('client_id'):
|
||||
print("======CLIENT_ID======")
|
||||
print(message.get('client_id'))
|
||||
|
||||
return {
|
||||
'client_id': message.get('client_id'),
|
||||
'redirect_uri': redirect_url
|
||||
}
|
||||
|
||||
|
||||
def register(self):
|
||||
""" Create a User on hub.erpnext.org and return username/password """
|
||||
data = {
|
||||
|
@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Hub Tracked Item', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
@ -0,0 +1,93 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-03-18 09:33:50.267762",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Item Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 1,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-03-18 09:34:01.757713",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Hub Node",
|
||||
"name": "Hub Tracked Item",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 1,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class HubTrackedItem(Document):
|
||||
pass
|
@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Hub Tracked Item", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Hub Tracked Item
|
||||
() => frappe.tests.make('Hub Tracked Item', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestHubTrackedItem(unittest.TestCase):
|
||||
pass
|
0
erpnext/hub_node/doctype/hub_users/__init__.py
Normal file
72
erpnext/hub_node/doctype/hub_users/hub_users.json
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-03-06 04:38:49.891787",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "User",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "User",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-03-06 04:41:17.916243",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Hub Node",
|
||||
"name": "Hub Users",
|
||||
"name_case": "",
|
||||
"owner": "test1@example.com",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
10
erpnext/hub_node/doctype/hub_users/hub_users.py
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class HubUsers(Document):
|
||||
pass
|
0
erpnext/hub_node/page/__init__.py
Normal file
@ -515,3 +515,5 @@ erpnext.patches.v10_0.update_hub_connector_domain
|
||||
erpnext.patches.v10_0.set_student_party_type
|
||||
erpnext.patches.v10_0.update_project_in_sle
|
||||
erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract
|
||||
erpnext.patches.v11_0.add_index_on_nestedset_doctypes
|
||||
erpnext.patches.v11_0.remove_modules_setup_page
|
||||
|
9
erpnext/patches/v11_0/add_index_on_nestedset_doctypes.py
Normal file
@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("agriculture", "doctype", "land_unit")
|
||||
for dt in ("Account", "Cost Center", "File", "Employee", "Land Unit", "Task", "Customer Group", "Sales Person", "Territory"):
|
||||
frappe.get_doc("DocType", dt).run_module_method("on_doctype_update")
|
8
erpnext/patches/v11_0/remove_modules_setup_page.py
Normal file
@ -0,0 +1,8 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.delete_doc("Page", "modules_setup")
|
@ -15,10 +15,11 @@ def update_hr_permissions():
|
||||
# add set user permissions rights to HR Manager
|
||||
frappe.db.sql("""update `tabDocPerm` set `set_user_permissions`=1 where parent in ('Employee', 'Leave Application')
|
||||
and role='HR Manager' and permlevel=0 and `read`=1""")
|
||||
|
||||
# apply user permissions on Employee and Leave Application
|
||||
frappe.db.sql("""update `tabDocPerm` set `apply_user_permissions`=1 where parent in ('Employee', 'Leave Application')
|
||||
and role in ('Employee', 'Leave Approver') and permlevel=0 and `read`=1""")
|
||||
docperm_meta = frappe.get_meta('DocPerm')
|
||||
if docperm_meta.get_field('apply_user_permissions'):
|
||||
# apply user permissions on Employee and Leave Application
|
||||
frappe.db.sql("""update `tabDocPerm` set `apply_user_permissions`=1 where parent in ('Employee', 'Leave Application')
|
||||
and role in ('Employee', 'Leave Approver') and permlevel=0 and `read`=1""")
|
||||
|
||||
frappe.clear_cache()
|
||||
|
||||
|
@ -236,3 +236,6 @@ def add_multiple_tasks(data, parent):
|
||||
new_doc['subject'] = d.get("subject")
|
||||
new_task = frappe.get_doc(new_doc)
|
||||
new_task.insert()
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Task", ["lft", "rgt"])
|
@ -53,16 +53,6 @@ frappe.ui.form.on("Timesheet", {
|
||||
|
||||
if (frm.doc.docstatus < 1) {
|
||||
|
||||
$.each(frm.doc.time_logs || [], function(i, row) {
|
||||
if(row.from_time && !row.completed) {
|
||||
if (row.to_time && frappe.datetime.now_datetime() > row.to_time) {
|
||||
frappe.utils.play_sound("alert");
|
||||
frappe.msgprint(__(`Timer exceeded the expected hours for activity ${row.activity_type} in row ${row.idx}.`));
|
||||
}
|
||||
}
|
||||
frm.refresh_fields();
|
||||
});
|
||||
|
||||
let button = 'Start Timer';
|
||||
$.each(frm.doc.time_logs || [], function(i, row) {
|
||||
if ((row.from_time <= frappe.datetime.now_datetime()) && !row.completed) {
|
||||
@ -72,8 +62,16 @@ frappe.ui.form.on("Timesheet", {
|
||||
|
||||
frm.add_custom_button(__(button), function() {
|
||||
var flag = true;
|
||||
// Fetch the row for timer where activity is not completed and from_time is not <= now_time
|
||||
$.each(frm.doc.time_logs || [], function(i, row) {
|
||||
// Fetch the row for which from_time is not present
|
||||
if (flag && row.activity_type && !row.from_time){
|
||||
erpnext.timesheet.timer(frm, row);
|
||||
row.from_time = frappe.datetime.now_datetime();
|
||||
frm.refresh_fields("time_logs");
|
||||
frm.save();
|
||||
flag = false;
|
||||
}
|
||||
// Fetch the row for timer where activity is not completed and from_time is before now_time
|
||||
if (flag && row.from_time <= frappe.datetime.now_datetime() && !row.completed) {
|
||||
let timestamp = moment(frappe.datetime.now_datetime()).diff(moment(row.from_time),"seconds");
|
||||
erpnext.timesheet.timer(frm, row, timestamp);
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"css/erpnext.css": [
|
||||
"public/less/erpnext.less"
|
||||
"public/less/erpnext.less",
|
||||
"public/less/hub.less"
|
||||
],
|
||||
"js/erpnext-web.min.js": [
|
||||
"public/js/website_utils.js",
|
||||
@ -21,7 +22,7 @@
|
||||
"public/js/pos/pos.html",
|
||||
"public/js/pos/pos_bill_item.html",
|
||||
"public/js/pos/pos_bill_item_new.html",
|
||||
"public/js/pos/pos_selected_item.html",
|
||||
"public/js/pos/pos_selected_item.html",
|
||||
"public/js/pos/pos_item.html",
|
||||
"public/js/pos/pos_tax_row.html",
|
||||
"public/js/pos/customer_toolbar.html",
|
||||
|
@ -1,130 +0,0 @@
|
||||
body[data-route^="Hub/"] .freeze .image-view-container .list-row-col {
|
||||
background-color: #fafbfc;
|
||||
color: #fafbfc;
|
||||
}
|
||||
body[data-route^="Hub/"] .freeze .image-view-container .placeholder-text {
|
||||
color: #fafbfc;
|
||||
}
|
||||
body[data-route^="Hub/"] .freeze {
|
||||
display: none;
|
||||
}
|
||||
body[data-route^="Hub/"] .image-view-container {
|
||||
justify-content: space-around;
|
||||
}
|
||||
.img-wrapper {
|
||||
border: 1px solid #d1d8dd;
|
||||
border-radius: 3px;
|
||||
padding: 12px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.img-wrapper .helper {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
/* hub */
|
||||
div[data-page-route="hub"] .page-head {
|
||||
height: 80px;
|
||||
}
|
||||
div[data-page-route="hub"] .page-head .title-text {
|
||||
cursor: pointer;
|
||||
}
|
||||
div[data-page-route="hub"] .page-content {
|
||||
margin-top: 80px;
|
||||
}
|
||||
div[data-page-route="hub"] .page-title h1 {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
div[data-page-route="hub"] .account-details {
|
||||
margin-top: 20px;
|
||||
}
|
||||
div[data-page-route="hub"] [data-original-title="Search"] {
|
||||
float: right;
|
||||
width: 220px;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-main-section {
|
||||
padding: 30px;
|
||||
}
|
||||
div[data-page-route="hub"] .listing-body {
|
||||
margin: 0;
|
||||
}
|
||||
div[data-page-route="hub"] .main-list-section {
|
||||
padding: 0;
|
||||
}
|
||||
div[data-page-route="hub"] .side-list-section {
|
||||
padding: 0;
|
||||
}
|
||||
div[data-page-route="hub"] .item-list-header h3 {
|
||||
font-weight: normal;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page h2 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .item-header {
|
||||
display: flex;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .item-page-image {
|
||||
flex: 1;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .title-content {
|
||||
flex: 3;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .title-content .description {
|
||||
margin: 30px 0px;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .title-content .actions {
|
||||
margin-top: 30px;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .title-content .actions .rfq-btn.disabled {
|
||||
background-color: #b1bdca;
|
||||
color: #fff;
|
||||
border-color: #b1bdca;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-page .company-items {
|
||||
margin-top: 40px;
|
||||
}
|
||||
div[data-page-route="hub"] .company-header {
|
||||
display: flex;
|
||||
}
|
||||
div[data-page-route="hub"] .item-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-wrapper {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
div[data-page-route="hub"] .img-wrapper {
|
||||
border: 1px solid #d1d8dd;
|
||||
border-radius: 3px;
|
||||
padding: 12px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
div[data-page-route="hub"] .img-wrapper img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
div[data-page-route="hub"] .img-wrapper .helper {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
div[data-page-route="hub"] .img-wrapper .standard-image {
|
||||
font-size: 72px;
|
||||
border: none;
|
||||
background-color: #fafbfc;
|
||||
}
|
||||
div[data-page-route="hub"] .hub-item-title {
|
||||
width: 100%;
|
||||
}
|
||||
div[data-page-route="hub"] .breadcrumb {
|
||||
padding-left: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
@ -1,76 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="svg3718"
|
||||
xml:space="preserve"
|
||||
width="162.12097"
|
||||
height="162.3004"
|
||||
viewBox="0 0 162.12098 162.3004"
|
||||
sodipodi:docname="hub_logo.svg"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
|
||||
id="metadata3724"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs3722"><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3734"><path
|
||||
d="M 0,600 H 1000 V 0 H 0 Z"
|
||||
id="path3732"
|
||||
inkscape:connector-curvature="0" /></clipPath></defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="740"
|
||||
inkscape:window-height="449"
|
||||
id="namedview3720"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.1278353"
|
||||
inkscape:cx="108.86803"
|
||||
inkscape:cy="50.640564"
|
||||
inkscape:window-x="605"
|
||||
inkscape:window-y="98"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g3726"
|
||||
fit-margin-top="10"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="10" /><g
|
||||
id="g3726"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="hub logo"
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,-579.98759,522.65266)"><g
|
||||
id="g3728"><g
|
||||
id="g3730"
|
||||
clip-path="url(#clipPath3734)"><g
|
||||
id="g3740"
|
||||
transform="translate(469.3467,296.2959)"><path
|
||||
d="m 0,0 c -16.597,0 -31.587,12.581 -32.298,13.186 l -2.058,1.751 1.131,2.452 c 0.44,0.956 11.012,23.476 30.001,27.662 l 1.527,0.336 C 10.532,48.083 22.675,40.327 25.37,28.098 28.065,15.871 20.307,3.728 8.081,1.033 L 6.551,0.698 C 4.36,0.214 2.167,0 0,0"
|
||||
style="fill:#6be273;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3742"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g3744"
|
||||
transform="translate(519.9316,324.9663)"><path
|
||||
d="m 0,0 c -8.052,0 -16.033,3.513 -21.457,10.266 -4.599,5.724 -6.689,12.896 -5.892,20.196 0.797,7.297 4.39,13.85 10.111,18.446 l 1.524,1.225 c 7.78,6.245 18.871,9.487 32.081,9.388 9.773,-0.076 17.263,-1.928 17.578,-2.006 l 2.621,-0.657 0.074,-2.699 C 36.675,52.862 37.313,22.21 18.708,7.269 L 17.184,6.044 C 12.118,1.977 6.044,0 0,0"
|
||||
style="fill:#49c44c;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3746"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g3748"
|
||||
transform="translate(533.21,367.6562)"><path
|
||||
d="m 0,0 c -5.312,-1.335 -13.328,-3.353 -20.459,-7.646 -8.907,-5.364 -13.925,-12.827 -14.923,-22.183 l -0.02,-0.188 v -14.901 c -3.873,3.824 -8.159,6.202 -12.809,7.101 -12.143,2.341 -23.14,-5.967 -29.049,-10.433 l 4.296,-5.686 c 5.024,3.797 14.373,10.864 23.402,9.122 5.207,-1.005 9.965,-4.887 14.16,-11.54 v -33.538 h 7.128 v 59.49 c 1.878,16.413 20.17,21.016 30.01,23.492 z"
|
||||
style="fill:#cef6d1;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3750"
|
||||
inkscape:connector-curvature="0" /></g></g></g></g></svg>
|
||||
viewBox="0 0 87.312496 91.397155"
|
||||
class="hub-icon"
|
||||
height="345.43808"
|
||||
width="330">
|
||||
<g
|
||||
transform="translate(121.51931,-138.66452)"
|
||||
id="layer1">
|
||||
<rect
|
||||
ry="13.229166"
|
||||
y="142.74918"
|
||||
x="-121.51931"
|
||||
height="87.3125"
|
||||
width="87.3125"
|
||||
id="rect828"
|
||||
style="opacity:1;vector-effect:none;fill:#89da29;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
rx="13.229166" />
|
||||
<path
|
||||
id="path830"
|
||||
d="m -121.51931,202.96343 v 13.86892 c 0,7.32897 5.90017,13.22917 13.22916,13.22917 h 60.854162 c 6.610072,0 12.056133,-4.80013 13.061216,-11.1187 -43.339761,0.1608 -54.359752,-16.03276 -87.144538,-15.97939 z"
|
||||
clip-path="none"
|
||||
style="opacity:1;vector-effect:none;fill:#63c923;fill-opacity:1;stroke:none;stroke-width:3.96875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
|
||||
<path
|
||||
id="path832"
|
||||
d="m -34.20681,202.96343 c -32.784694,-0.0533 -43.804846,16.14019 -87.14455,15.97939 1.00509,6.31857 6.45115,11.1187 13.06122,11.1187 h 60.854164 c 7.328992,0 13.229166,-5.9002 13.229166,-13.22917 z"
|
||||
clip-path="none"
|
||||
style="opacity:1;vector-effect:none;fill:#59b81c;fill-opacity:1;stroke:none;stroke-width:3.96875;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
|
||||
<path
|
||||
style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79375005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
|
||||
d="m -84.351263,175.75725 c -1.30945,0 -2.376091,1.06665 -2.376091,2.37608 v 10.02885 0.001 c 0.06583,4.83083 4.01156,8.73477 8.857351,8.73486 4.8718,5e-5 8.846821,-3.94421 8.871295,-8.81134 v -0.001 -9.95288 c 0,-1.30943 -1.066113,-2.37557 -2.375589,-2.37557 -1.309396,0 -2.376064,1.06614 -2.376064,2.37557 v 9.8888 c 0,2.26045 -1.858169,4.10983 -4.119642,4.10983 -2.263616,0 -4.105699,-1.82766 -4.105699,-4.08968 v -9.90844 c 0,-1.30943 -1.066138,-2.37608 -2.375561,-2.37608 z m -20.887107,0.0925 c -1.30943,0 -2.37609,1.06717 -2.37609,2.3766 v 16.45119 c 0,1.30944 1.06666,2.37609 2.37609,2.37609 1.30945,0 2.37556,-1.06665 2.37556,-2.37609 v -5.97327 h 8.22534 v 5.97327 c 0,1.30944 1.066641,2.37609 2.376091,2.37609 1.309423,0 2.375561,-1.06665 2.375561,-2.37609 v -16.45119 c 0,-1.30943 -1.066138,-2.3766 -2.375561,-2.3766 -1.30945,0 -2.376091,1.06717 -2.376091,2.3766 v 5.72627 h -8.22534 v -5.72627 c 0,-1.30943 -1.06611,-2.3766 -2.37556,-2.3766 z m 41.77419,0 c -0.654712,0 -1.248675,0.26711 -1.678967,0.69764 -0.05368,0.0537 -0.105119,0.10983 -0.153458,0.16846 v 5.3e-4 c -0.04839,0.0586 -0.09427,0.11929 -0.136949,0.18242 v 5.3e-4 c -0.256381,0.37936 -0.406691,0.83617 -0.406691,1.32705 v 16.45119 c 0,0.1635 0.01693,0.3242 0.04858,0.47852 0.09512,0.46331 0.32594,0.87828 0.64852,1.20096 0.161369,0.16136 0.345308,0.29938 0.547264,0.40928 v 0 c 0.134567,0.0732 0.276781,0.13403 0.425318,0.18035 v 0 c 0.148537,0.0463 0.303186,0.0783 0.462518,0.0946 v 0 c 0.07959,0.008 0.160708,0.0124 0.242358,0.0124 h 8.33181 c 0.08747,0 0.167931,-0.0145 0.251142,-0.0238 l 0.09509,0.005 c 0.06019,0.003 0.119407,0.005 0.178779,0.006 h 0.0037 0.0048 c 3.578305,-2e-5 6.487954,-2.90916 6.487981,-6.48747 v -0.001 c -0.0026,-1.51334 -0.578009,-2.9475 -1.540484,-4.10673 0.962448,-1.15892 1.537785,-2.59314 1.540484,-4.10621 v -0.001 c -2.7e-5,-3.57831 -2.909676,-6.48744 -6.487981,-6.48746 h -0.533294 z m 8.865103,4.75062 c 0.96393,0 1.736831,0.77394 1.736831,1.73788 0,0.96394 -0.772901,1.73684 -1.736831,1.73684 v 0 h -0.532792 -5.955718 v -3.47317 h 5.956248 z m 0,8.21552 v 0 c 0.963507,5.3e-4 1.735799,0.77373 1.735799,1.73736 0,0.96394 -0.772901,1.73684 -1.736831,1.73684 h -0.0048 l -0.533294,0.0119 h -5.951591 v -3.4742 h 5.959846 z"
|
||||
id="path834" />
|
||||
<path
|
||||
id="path838"
|
||||
d="m -77.859375,138.66406 c -9.653316,0 -18.439915,3.93483 -24.767575,10.28125 a 3.9691471,3.9691471 0 1 0 5.621091,5.60352 c 4.899576,-4.9141 11.6422,-7.94727 19.146484,-7.94727 7.501101,0 14.241542,3.03098 19.140625,7.94141 a 3.9691471,3.9691471 0 1 0 5.619141,-5.60547 c -6.327038,-6.34169 -15.110547,-10.27344 -24.759766,-10.27344 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#63c923;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.93750048;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 5.6 KiB |
@ -172,17 +172,17 @@ agriculture.TernaryPlot = class TernaryPlot {
|
||||
make_plot_marking() {
|
||||
let { triangle_side: t, spacing: s, scaling_factor: p } = this.config;
|
||||
|
||||
let clay = this.paper.text(t * Snap.cos(60) / 2, s + t * Snap.cos(30) / 2, "Clay").attr({
|
||||
let clay = this.paper.text(t * Snap.cos(60) / 2, s + t * Snap.cos(30) / 2, __("Clay")).attr({
|
||||
fill: frappe.ui.color.get('black')
|
||||
});
|
||||
clay.transform("r300");
|
||||
|
||||
let silt = this.paper.text(t, s + t * Snap.cos(30) / 2, "Silt").attr({
|
||||
let silt = this.paper.text(t, s + t * Snap.cos(30) / 2, __("Silt")).attr({
|
||||
fill: frappe.ui.color.get('black')
|
||||
});
|
||||
silt.transform("r60");
|
||||
|
||||
let sand = this.paper.text(35 + t * Snap.cos(60), 90 + t * Snap.cos(30), "Sand").attr({
|
||||
let sand = this.paper.text(35 + t * Snap.cos(60), 90 + t * Snap.cos(30), __("Sand")).attr({
|
||||
fill: frappe.ui.color.get('black')
|
||||
});
|
||||
sand.transform("r0");
|
||||
@ -229,4 +229,4 @@ agriculture.TernaryPlot = class TernaryPlot {
|
||||
if (typeof this.blip !== 'undefined')
|
||||
this.blip.remove();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -106,7 +106,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
}
|
||||
|
||||
if(
|
||||
this.frm.fields_dict["payment_terms_template"]
|
||||
this.frm.docstatus < 2
|
||||
&& this.frm.fields_dict["payment_terms_template"]
|
||||
&& this.frm.fields_dict["payment_schedule"]
|
||||
&& this.frm.doc.payment_terms_template
|
||||
&& !this.frm.doc.payment_schedule.length
|
||||
|
@ -7,25 +7,33 @@ frappe.views.HubFactory = frappe.views.Factory.extend({
|
||||
|
||||
const assets = {
|
||||
'List': [
|
||||
'/assets/erpnext/js/hub/hub_page.js',
|
||||
'/assets/erpnext/css/hub.css',
|
||||
'/assets/erpnext/js/hub/hub_listing.js',
|
||||
],
|
||||
'Form': [
|
||||
'/assets/erpnext/js/hub/hub_form.js',
|
||||
'/assets/erpnext/css/hub.css',
|
||||
'/assets/erpnext/js/hub/hub_form.js'
|
||||
]
|
||||
};
|
||||
frappe.model.with_doc('Hub Settings', 'Hub Settings', () => {
|
||||
this.hub_settings = frappe.get_doc('Hub Settings');
|
||||
|
||||
if (!erpnext.hub.pages[page_name]) {
|
||||
if(!frappe.is_online()) {
|
||||
this.render_offline_card();
|
||||
return;
|
||||
}
|
||||
if (!route[2]) {
|
||||
frappe.require(assets['List'], () => {
|
||||
erpnext.hub.pages[page_name] = new erpnext.hub[page+'Listing']({
|
||||
parent: this.make_page(true, page_name),
|
||||
hub_settings: this.hub_settings
|
||||
});
|
||||
window.hub_page = erpnext.hub.pages[page_name];
|
||||
if(page === 'Favourites') {
|
||||
erpnext.hub.pages[page_name] = new erpnext.hub['Favourites']({
|
||||
parent: this.make_page(true, page_name),
|
||||
hub_settings: this.hub_settings
|
||||
});
|
||||
} else {
|
||||
erpnext.hub.pages[page_name] = new erpnext.hub[page+'Listing']({
|
||||
parent: this.make_page(true, page_name),
|
||||
hub_settings: this.hub_settings
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
frappe.require(assets['Form'], () => {
|
||||
@ -35,13 +43,29 @@ frappe.views.HubFactory = frappe.views.Factory.extend({
|
||||
parent: this.make_page(true, page_name),
|
||||
hub_settings: this.hub_settings
|
||||
});
|
||||
window.hub_page = erpnext.hub.pages[page_name];
|
||||
});
|
||||
}
|
||||
window.hub_page = erpnext.hub.pages[page_name];
|
||||
} else {
|
||||
frappe.container.change_to(page_name);
|
||||
window.hub_page = erpnext.hub.pages[page_name];
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render_offline_card() {
|
||||
let html = `<div class='page-card' style='margin: 140px auto;'>
|
||||
<div class='page-card-head'>
|
||||
<span class='indicator red'>${'Failed to connect'}</span>
|
||||
</div>
|
||||
<p>${ __("Please check your network connection.") }</p>
|
||||
<div><a href='#Hub/Item' class='btn btn-primary btn-sm'>
|
||||
${ __("Reload") }</a></div>
|
||||
</div>`;
|
||||
|
||||
let page = $('#body_div');
|
||||
page.append(html);
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
frappe.provide('erpnext.hub');
|
||||
|
||||
erpnext.hub.HubForm = class HubForm extends frappe.views.BaseList {
|
||||
erpnext.hub.HubDetailsPage = class HubDetailsPage extends frappe.views.BaseList {
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.method = 'erpnext.hub_node.get_details';
|
||||
@ -8,6 +8,25 @@ erpnext.hub.HubForm = class HubForm extends frappe.views.BaseList {
|
||||
this.page_name = route[2];
|
||||
}
|
||||
|
||||
setup_fields() {
|
||||
return this.get_meta()
|
||||
.then(r => {
|
||||
this.meta = r.message.meta || this.meta;
|
||||
this.categories = r.message.categories || [];
|
||||
this.bootstrap_data(r.message);
|
||||
|
||||
this.getFormFields();
|
||||
});
|
||||
}
|
||||
|
||||
bootstrap_data() { }
|
||||
|
||||
get_meta() {
|
||||
return new Promise(resolve =>
|
||||
frappe.call('erpnext.hub_node.get_meta', {doctype: 'Hub ' + this.doctype}, resolve));
|
||||
}
|
||||
|
||||
|
||||
set_breadcrumbs() {
|
||||
frappe.breadcrumbs.add({
|
||||
label: __('Hub'),
|
||||
@ -27,6 +46,45 @@ erpnext.hub.HubForm = class HubForm extends frappe.views.BaseList {
|
||||
|
||||
setup_sort_selector() { }
|
||||
|
||||
// let category = this.quick_view.get_values().hub_category;
|
||||
// return new Promise((resolve, reject) => {
|
||||
// frappe.call({
|
||||
// method: 'erpnext.hub_node.update_category',
|
||||
// args: {
|
||||
// hub_item_code: values.hub_item_code,
|
||||
// category: category,
|
||||
// },
|
||||
// callback: (r) => {
|
||||
// resolve();
|
||||
// },
|
||||
// freeze: true
|
||||
// }).fail(reject);
|
||||
// });
|
||||
|
||||
get_timeline() {
|
||||
return `<div class="timeline">
|
||||
<div class="timeline-head">
|
||||
</div>
|
||||
<div class="timeline-new-email">
|
||||
<button class="btn btn-default btn-reply-email btn-xs">
|
||||
${__("Reply")}
|
||||
</button>
|
||||
</div>
|
||||
<div class="timeline-items"></div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
get_footer() {
|
||||
return `<div class="form-footer">
|
||||
<div class="after-save">
|
||||
<div class="form-comments"></div>
|
||||
</div>
|
||||
<div class="pull-right scroll-to-top">
|
||||
<a onclick="frappe.utils.scroll_to(0)"><i class="fa fa-chevron-up text-muted"></i></a>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
get_args() {
|
||||
return {
|
||||
hub_sync_id: this.unique_id,
|
||||
@ -48,108 +106,379 @@ erpnext.hub.HubForm = class HubForm extends frappe.views.BaseList {
|
||||
<span class="helper"></span>` :
|
||||
`<div class="standard-image">${frappe.get_abbr(this.page_title)}</div>`;
|
||||
|
||||
this.sidebar.remove_item('image');
|
||||
this.sidebar.add_item({
|
||||
name: 'image',
|
||||
label: image_html
|
||||
});
|
||||
|
||||
let fields = this.get_field_configs();
|
||||
if(!this.form) {
|
||||
let fields = this.formFields;
|
||||
this.form = new frappe.ui.FieldGroup({
|
||||
parent: this.$result,
|
||||
fields
|
||||
});
|
||||
this.form.make();
|
||||
}
|
||||
|
||||
this.form = new frappe.ui.FieldGroup({
|
||||
parent: this.$result,
|
||||
fields
|
||||
});
|
||||
if(this.data.hub_category) {
|
||||
this.form.fields_dict.set_category.hide();
|
||||
}
|
||||
|
||||
this.form.make();
|
||||
this.form.set_values(this.data);
|
||||
this.$result.show();
|
||||
|
||||
this.$timelineList && this.$timelineList.empty();
|
||||
if(this.data.reviews && this.data.reviews.length) {
|
||||
this.data.reviews.map(review => {
|
||||
this.addReviewToTimeline(review);
|
||||
})
|
||||
}
|
||||
|
||||
this.postRender()
|
||||
}
|
||||
|
||||
toggle_result_area() {
|
||||
this.$result.toggle(this.unique_id);
|
||||
this.$paging_area.toggle(this.data.length > 0);
|
||||
this.$no_result.toggle(this.data.length == 0);
|
||||
postRender() {}
|
||||
|
||||
const show_more = (this.start + this.page_length) <= this.data.length;
|
||||
this.$paging_area.find('.btn-more')
|
||||
.toggle(show_more);
|
||||
attachFooter() {
|
||||
let footerHtml = `<div class="form-footer">
|
||||
<div class="form-comments"></div>
|
||||
<div class="pull-right scroll-to-top">
|
||||
<a onclick="frappe.utils.scroll_to(0)"><i class="fa fa-chevron-up text-muted"></i></a>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
let parent = $('<div>').appendTo(this.page.main.parent());
|
||||
this.$footer = $(footerHtml).appendTo(parent);
|
||||
}
|
||||
|
||||
attachTimeline() {
|
||||
let timelineHtml = `<div class="timeline">
|
||||
<div class="timeline-head">
|
||||
</div>
|
||||
<div class="timeline-new-email">
|
||||
<button class="btn btn-default btn-reply-email btn-xs">
|
||||
${ __("Reply") }
|
||||
</button>
|
||||
</div>
|
||||
<div class="timeline-items"></div>
|
||||
</div>`;
|
||||
|
||||
let parent = this.$footer.find(".form-comments");
|
||||
this.$timeline = $(timelineHtml).appendTo(parent);
|
||||
|
||||
this.$timelineList = this.$timeline.find(".timeline-items");
|
||||
}
|
||||
|
||||
attachReviewArea() {
|
||||
this.comment_area = new frappe.ui.ReviewArea({
|
||||
parent: this.$footer.find('.timeline-head'),
|
||||
mentions: [],
|
||||
on_submit: (val) => {
|
||||
val.user = frappe.session.user;
|
||||
val.username = frappe.session.user_fullname;
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.send_review',
|
||||
args: {
|
||||
hub_item_code: this.data.hub_item_code,
|
||||
review: val
|
||||
},
|
||||
callback: (r) => {
|
||||
this.refresh();
|
||||
this.comment_area.reset();
|
||||
},
|
||||
freeze: true
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addReviewToTimeline(data) {
|
||||
let username = data.username || data.user || __("Anonymous")
|
||||
let imageHtml = data.user_image
|
||||
? `<div class="avatar-frame" style="background-image: url(${data.user_image})"></div>`
|
||||
: `<div class="standard-image" style="background-color: #fafbfc">${frappe.get_abbr(username)}</div>`
|
||||
|
||||
let editHtml = data.own
|
||||
? `<div class="pull-right hidden-xs close-btn-container">
|
||||
<span class="small text-muted">
|
||||
${'data.delete'}
|
||||
</span>
|
||||
</div>
|
||||
<div class="pull-right edit-btn-container">
|
||||
<span class="small text-muted">
|
||||
${'data.edit'}
|
||||
</span>
|
||||
</div>`
|
||||
: '';
|
||||
|
||||
let ratingHtml = '';
|
||||
|
||||
for(var i = 0; i < 5; i++) {
|
||||
let starIcon = 'fa-star-o'
|
||||
if(i < data.rating) {
|
||||
starIcon = 'fa-star';
|
||||
}
|
||||
ratingHtml += `<i class="fa fa-fw ${starIcon} star-icon" data-idx='${i}'></i>`;
|
||||
}
|
||||
|
||||
$(this.getTimelineItem(data, imageHtml, editHtml, ratingHtml))
|
||||
.appendTo(this.$timelineList);
|
||||
}
|
||||
|
||||
getTimelineItem(data, imageHtml, editHtml, ratingHtml) {
|
||||
return `<div class="media timeline-item user-content" data-doctype="${''}" data-name="${''}">
|
||||
<span class="pull-left avatar avatar-medium hidden-xs" style="margin-top: 1px">
|
||||
${imageHtml}
|
||||
</span>
|
||||
|
||||
<div class="pull-left media-body">
|
||||
<div class="media-content-wrapper">
|
||||
<div class="action-btns">${editHtml}</div>
|
||||
|
||||
<div class="comment-header clearfix small ${'linksActive'}">
|
||||
<span class="pull-left avatar avatar-small visible-xs">
|
||||
${imageHtml}
|
||||
</span>
|
||||
|
||||
<div class="asset-details">
|
||||
<span class="author-wrap">
|
||||
<i class="octicon octicon-quote hidden-xs fa-fw"></i>
|
||||
<span>${data.username}</span>
|
||||
</span>
|
||||
<a href="#Form/${''}" class="text-muted">
|
||||
<span class="text-muted hidden-xs">–</span>
|
||||
<span class="indicator-right ${'green'}
|
||||
delivery-status-indicator">
|
||||
<span class="hidden-xs">${data.pretty_date}</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a class="text-muted reply-link pull-right timeline-content-show"
|
||||
title="${__('Reply')}"> ${''} </a>
|
||||
<span class="comment-likes hidden-xs">
|
||||
<i class="octicon octicon-heart like-action text-extra-muted not-liked fa-fw">
|
||||
</i>
|
||||
<span class="likes-count text-muted">10</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="reply timeline-content-show">
|
||||
<div class="timeline-item-content">
|
||||
<p class="text-muted small">
|
||||
<b>${data.subject}</b>
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p class="text-muted small">
|
||||
${ratingHtml}
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
${data.content}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
prepareFormFields(fields, fieldnames) {
|
||||
return fields
|
||||
.filter(field => fieldnames.includes(field.fieldname))
|
||||
.map(field => {
|
||||
let {
|
||||
label,
|
||||
fieldname,
|
||||
fieldtype,
|
||||
} = field;
|
||||
let read_only = 1;
|
||||
return {
|
||||
label,
|
||||
fieldname,
|
||||
fieldtype,
|
||||
read_only,
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
erpnext.hub.ItemPage = class ItemPage extends erpnext.hub.HubForm{
|
||||
erpnext.hub.ItemPage = class ItemPage extends erpnext.hub.HubDetailsPage {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
|
||||
this.show();
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Item';
|
||||
this.image_field_name = 'image';
|
||||
}
|
||||
|
||||
get_field_configs() {
|
||||
let fields = [];
|
||||
this.fields.map(fieldname => {
|
||||
fields.push({
|
||||
label: toTitle(frappe.model.unscrub(fieldname)),
|
||||
fieldname,
|
||||
fieldtype: 'Data',
|
||||
read_only: 1
|
||||
});
|
||||
});
|
||||
|
||||
let category_field = {
|
||||
label: 'Hub Category',
|
||||
fieldname: 'hub_category',
|
||||
fieldtype: 'Data'
|
||||
}
|
||||
|
||||
if(this.data.company_name === this.hub_settings.company) {
|
||||
this.page.set_primary_action(__('Update'), () => {
|
||||
this.update_on_hub();
|
||||
}, 'octicon octicon-plus');
|
||||
} else {
|
||||
category_field.read_only = 1;
|
||||
}
|
||||
|
||||
fields.unshift(category_field);
|
||||
|
||||
return fields;
|
||||
setup_page_head() {
|
||||
super.setup_page_head();
|
||||
this.set_primary_action();
|
||||
}
|
||||
|
||||
update_on_hub() {
|
||||
setup_side_bar() {
|
||||
this.setup_side_bar();
|
||||
this.attachFooter();
|
||||
this.attachTimeline();
|
||||
this.attachReviewArea();
|
||||
}
|
||||
|
||||
set_primary_action() {
|
||||
let item = this.data;
|
||||
this.page.set_primary_action(__('Request a Quote'), () => {
|
||||
this.show_rfq_modal()
|
||||
.then(values => {
|
||||
item.item_code = values.item_code;
|
||||
delete values.item_code;
|
||||
|
||||
const supplier = values;
|
||||
return [item, supplier];
|
||||
})
|
||||
.then(([item, supplier]) => {
|
||||
return this.make_rfq(item, supplier, this.page.btn_primary);
|
||||
})
|
||||
.then(r => {
|
||||
console.log(r);
|
||||
if (r.message && r.message.rfq) {
|
||||
this.page.btn_primary.addClass('disabled').html(`<span><i class='fa fa-check'></i> ${__('Quote Requested')}</span>`);
|
||||
} else {
|
||||
throw r;
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e); //eslint-disable-line
|
||||
});
|
||||
}, 'octicon octicon-plus');
|
||||
}
|
||||
|
||||
make_rfq(item, supplier, btn) {
|
||||
console.log(supplier);
|
||||
return new Promise((resolve, reject) => {
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.update_category',
|
||||
args: { item: this.unique_id, category: this.form.get_value('hub_category') },
|
||||
method: 'erpnext.hub_node.make_rfq_and_send_opportunity',
|
||||
args: { item, supplier },
|
||||
callback: resolve,
|
||||
freeze: true
|
||||
btn,
|
||||
}).fail(reject);
|
||||
});
|
||||
}
|
||||
|
||||
setup_fields() {
|
||||
this.fields = ['hub_item_code', 'item_name', 'item_code', 'description',
|
||||
'seller', 'company_name', 'country'];
|
||||
postRender() {
|
||||
this.categoryDialog = new frappe.ui.Dialog({
|
||||
title: __('Suggest Category'),
|
||||
fields: [
|
||||
{
|
||||
label: __('Category'),
|
||||
fieldname: 'category',
|
||||
fieldtype: 'Autocomplete',
|
||||
options: this.categories,
|
||||
reqd: 1
|
||||
}
|
||||
],
|
||||
primary_action_label: __("Send"),
|
||||
primary_action: () => {
|
||||
let values = this.categoryDialog.get_values();
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.update_category',
|
||||
args: {
|
||||
hub_item_code: this.data.hub_item_code,
|
||||
category: values.category
|
||||
},
|
||||
callback: () => {
|
||||
this.categoryDialog.hide();
|
||||
this.refresh();
|
||||
},
|
||||
freeze: true
|
||||
}).fail(() => {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getFormFields() {
|
||||
let colOneFieldnames = ['item_name', 'item_code', 'description'];
|
||||
let colTwoFieldnames = ['seller', 'company_name', 'country'];
|
||||
let colOneFields = this.prepareFormFields(this.meta.fields, colOneFieldnames);
|
||||
let colTwoFields = this.prepareFormFields(this.meta.fields, colTwoFieldnames);
|
||||
|
||||
let miscFields = [
|
||||
{
|
||||
label: __('Category'),
|
||||
fieldname: 'hub_category',
|
||||
fieldtype: 'Data',
|
||||
read_only: 1
|
||||
},
|
||||
|
||||
{
|
||||
label: __('Suggest Category?'),
|
||||
fieldname: 'set_category',
|
||||
fieldtype: 'Button',
|
||||
click: () => {
|
||||
this.categoryDialog.show();
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
fieldname: 'cb1',
|
||||
fieldtype: 'Column Break'
|
||||
}
|
||||
];
|
||||
this.formFields = colOneFields.concat(miscFields, colTwoFields);
|
||||
}
|
||||
|
||||
show_rfq_modal() {
|
||||
let item = this.data;
|
||||
return new Promise(res => {
|
||||
let fields = [
|
||||
{ label: __('Item Code'), fieldtype: 'Data', fieldname: 'item_code', default: item.item_code },
|
||||
{ fieldtype: 'Column Break' },
|
||||
{ label: __('Item Group'), fieldtype: 'Link', fieldname: 'item_group', default: item.item_group },
|
||||
{ label: __('Supplier Details'), fieldtype: 'Section Break' },
|
||||
{ label: __('Supplier Name'), fieldtype: 'Data', fieldname: 'supplier_name', default: item.company_name },
|
||||
{ label: __('Supplier Email'), fieldtype: 'Data', fieldname: 'supplier_email', default: item.seller },
|
||||
{ fieldtype: 'Column Break' },
|
||||
{ label: __('Supplier Type'), fieldname: 'supplier_type',
|
||||
fieldtype: 'Link', options: 'Supplier Type' }
|
||||
];
|
||||
fields = fields.map(f => { f.reqd = 1; return f; });
|
||||
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Request for Quotation'),
|
||||
fields: fields,
|
||||
primary_action_label: __('Send'),
|
||||
primary_action: (values) => {
|
||||
res(values);
|
||||
d.hide();
|
||||
}
|
||||
});
|
||||
|
||||
d.show();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.hub.CompanyPage = class CompanyPage extends erpnext.hub.HubForm{
|
||||
erpnext.hub.CompanyPage = class CompanyPage extends erpnext.hub.HubDetailsPage {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
|
||||
this.show();
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Company';
|
||||
this.image_field_name = 'company_logo';
|
||||
}
|
||||
|
||||
get_field_configs() {
|
||||
let fields = [];
|
||||
this.fields.map(fieldname => {
|
||||
fields.push({
|
||||
label: toTitle(frappe.model.unscrub(fieldname)),
|
||||
fieldname,
|
||||
fieldtype: 'Data',
|
||||
read_only: 1
|
||||
});
|
||||
});
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
setup_fields() {
|
||||
this.fields = ['company_name', 'description', 'route', 'country', 'seller', 'site_name'];
|
||||
getFormFields() {
|
||||
let fieldnames = ['company_name', 'description', 'route', 'country', 'seller', 'site_name'];;
|
||||
this.formFields = this.prepareFormFields(this.meta.fields, fieldnames);
|
||||
}
|
||||
}
|
||||
|
726
erpnext/public/js/hub/hub_listing.js
Normal file
@ -0,0 +1,726 @@
|
||||
frappe.provide('erpnext.hub');
|
||||
|
||||
erpnext.hub.HubListing = class HubListing extends frappe.views.BaseList {
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.page_title = __('');
|
||||
this.method = 'erpnext.hub_node.get_list';
|
||||
|
||||
this.cache = {};
|
||||
|
||||
const route = frappe.get_route();
|
||||
this.page_name = route[1];
|
||||
|
||||
this.menu_items = this.menu_items.concat(this.get_menu_items());
|
||||
|
||||
this.imageFieldName = 'image';
|
||||
|
||||
this.show_filters = 0;
|
||||
}
|
||||
|
||||
set_title() {
|
||||
const title = this.page_title;
|
||||
let iconHtml = `<img class="hub-icon" src="assets/erpnext/images/hub_logo.svg">`;
|
||||
let titleHtml = `<span class="hub-page-title">${title}</span>`;
|
||||
this.page.set_title(iconHtml + titleHtml, '', false, title);
|
||||
}
|
||||
|
||||
setup_fields() {
|
||||
return this.get_meta()
|
||||
.then(r => {
|
||||
this.meta = r.message.meta || this.meta;
|
||||
frappe.model.sync(this.meta);
|
||||
this.bootstrap_data(r.message);
|
||||
|
||||
this.prepareFormFields();
|
||||
});
|
||||
}
|
||||
|
||||
get_meta() {
|
||||
return new Promise(resolve =>
|
||||
frappe.call('erpnext.hub_node.get_meta', {doctype: this.doctype}, resolve));
|
||||
}
|
||||
|
||||
set_breadcrumbs() { }
|
||||
|
||||
prepareFormFields() { }
|
||||
|
||||
bootstrap_data() { }
|
||||
|
||||
get_menu_items() {
|
||||
const items = [
|
||||
{
|
||||
label: __('Hub Settings'),
|
||||
action: () => frappe.set_route('Form', 'Hub Settings'),
|
||||
standard: true
|
||||
},
|
||||
{
|
||||
label: __('Favourites'),
|
||||
action: () => frappe.set_route('Hub', 'Favourites'),
|
||||
standard: true
|
||||
},
|
||||
// {
|
||||
// label: __('Toggle Sidebar'),
|
||||
// action: () => this.toggle_side_bar(),
|
||||
// standard: true
|
||||
// }
|
||||
];
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
setup_side_bar() {
|
||||
this.sidebar = new frappe.ui.Sidebar({
|
||||
wrapper: this.page.wrapper.find('.layout-side-section'),
|
||||
css_class: 'hub-sidebar'
|
||||
});
|
||||
}
|
||||
|
||||
setup_sort_selector() {
|
||||
this.sort_selector = new frappe.ui.SortSelector({
|
||||
parent: this.filter_area.$filter_list_wrapper,
|
||||
doctype: this.doctype,
|
||||
args: this.order_by,
|
||||
onchange: () => this.refresh(true)
|
||||
});
|
||||
}
|
||||
|
||||
setup_view() { }
|
||||
|
||||
get_args() {
|
||||
return {
|
||||
doctype: this.doctype,
|
||||
start: this.start,
|
||||
limit: this.page_length,
|
||||
order_by: this.order_by,
|
||||
// fields: this.fields,
|
||||
filters: this.get_filters_for_args()
|
||||
};
|
||||
}
|
||||
|
||||
update_data(r) {
|
||||
const data = r.message;
|
||||
|
||||
if (this.start === 0) {
|
||||
this.data = data;
|
||||
} else {
|
||||
this.data = this.data.concat(data);
|
||||
}
|
||||
|
||||
this.data_dict = {};
|
||||
}
|
||||
|
||||
freeze(toggle) {
|
||||
// if(!this.$freeze) return;
|
||||
// this.$freeze.toggle(toggle);
|
||||
// if (this.$freeze.find('.image-view-container').length) return;
|
||||
|
||||
// const html = Array.from(new Array(4)).map(d => this.card_html({
|
||||
// name: 'Loading...',
|
||||
// item_name: 'Loading...'
|
||||
// })).join('');
|
||||
|
||||
// this.$freeze.html(`<div class="image-view-container border-top">${html}</div>`);
|
||||
}
|
||||
|
||||
render() {
|
||||
this.data_dict = {};
|
||||
this.render_image_view();
|
||||
|
||||
this.setup_quick_view();
|
||||
this.setup_like();
|
||||
}
|
||||
|
||||
render_offline_card() {
|
||||
let html = `<div class='page-card'>
|
||||
<div class='page-card-head'>
|
||||
<span class='indicator red'>
|
||||
{{ _("Payment Cancelled") }}</span>
|
||||
</div>
|
||||
<p>${ __("Your payment is cancelled.") }</p>
|
||||
<div><a href='' class='btn btn-primary btn-sm'>
|
||||
${ __("Continue") }</a></div>
|
||||
</div>`;
|
||||
|
||||
let page = this.page.wrapper.find('.layout-side-section')
|
||||
page.append(html);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
render_image_view() {
|
||||
var html = this.data.map(this.item_html.bind(this)).join("");
|
||||
|
||||
if (this.start === 0) {
|
||||
// ${this.getHeaderHtml()}
|
||||
this.$result.html(`
|
||||
<div class="image-view-container small">
|
||||
${html}
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
if(this.data.length) {
|
||||
this.doc = this.data[0];
|
||||
}
|
||||
|
||||
this.data.map(this.loadImage.bind(this));
|
||||
|
||||
this.data_dict = {};
|
||||
this.data.map(d => {
|
||||
this.data_dict[d.hub_item_code] = d;
|
||||
});
|
||||
}
|
||||
|
||||
getHeaderHtml(title, image, content) {
|
||||
// let company_html =
|
||||
return `
|
||||
<header class="list-row-head text-muted small">
|
||||
<div style="display: flex;">
|
||||
<div class="list-header-icon">
|
||||
<img title="${title}" alt="${title}" src="${image}">
|
||||
</div>
|
||||
<div class="list-header-info">
|
||||
<h5>
|
||||
${title}
|
||||
</h5>
|
||||
<span class="margin-vertical-10 level-item">
|
||||
${content}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
`;
|
||||
}
|
||||
|
||||
renderHeader() {
|
||||
return `<header class="level list-row-head text-muted small">
|
||||
<div class="level-left list-header-subject">
|
||||
<div class="list-row-col list-subject level ">
|
||||
<img title="Riadco%20Group" alt="Riadco Group" src="https://cdn.pbrd.co/images/HdaPxcg.png">
|
||||
<span class="level-item">Products by Blah blah</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-left checkbox-actions">
|
||||
<div class="level list-subject">
|
||||
<input class="level-item list-check-all hidden-xs" type="checkbox" title="${__("Select All")}">
|
||||
<span class="level-item list-header-meta"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="level-right">
|
||||
${''}
|
||||
</div>
|
||||
</header>`;
|
||||
}
|
||||
|
||||
get_image_html(encoded_name, src, alt_text) {
|
||||
return `<img data-name="${encoded_name}" src="${ src }" alt="${ alt_text }">`;
|
||||
}
|
||||
|
||||
get_image_placeholder(title) {
|
||||
return `<span class="placeholder-text">${ frappe.get_abbr(title) }</span>`;
|
||||
}
|
||||
|
||||
loadImage(item) {
|
||||
item._name = encodeURI(item.name);
|
||||
const encoded_name = item._name;
|
||||
const title = strip_html(item[this.meta.title_field || 'name']);
|
||||
|
||||
let placeholder = this.get_image_placeholder(title);
|
||||
let $container = this.$result.find(`.image-field[data-name="${encoded_name}"]`);
|
||||
|
||||
if(!item[this.imageFieldName]) {
|
||||
$container.prepend(placeholder);
|
||||
$container.addClass('no-image');
|
||||
}
|
||||
|
||||
frappe.load_image(item[this.imageFieldName],
|
||||
(imageObj) => {
|
||||
$container.prepend(imageObj)
|
||||
},
|
||||
() => {
|
||||
$container.prepend(placeholder);
|
||||
$container.addClass('no-image');
|
||||
},
|
||||
(imageObj) => {
|
||||
imageObj.title = encoded_name;
|
||||
imageObj.alt = title;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
setup_quick_view() {
|
||||
if(this.quick_view) return;
|
||||
|
||||
this.quick_view = new frappe.ui.Dialog({
|
||||
title: 'Quick View',
|
||||
fields: this.formFields
|
||||
});
|
||||
this.quick_view.set_primary_action(__('Request a Quote'), () => {
|
||||
this.show_rfq_modal()
|
||||
.then(values => {
|
||||
item.item_code = values.item_code;
|
||||
delete values.item_code;
|
||||
|
||||
const supplier = values;
|
||||
return [item, supplier];
|
||||
})
|
||||
.then(([item, supplier]) => {
|
||||
return this.make_rfq(item, supplier, this.page.btn_primary);
|
||||
})
|
||||
.then(r => {
|
||||
console.log(r);
|
||||
if (r.message && r.message.rfq) {
|
||||
this.page.btn_primary.addClass('disabled').html(`<span><i class='fa fa-check'></i> ${__('Quote Requested')}</span>`);
|
||||
} else {
|
||||
throw r;
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e); //eslint-disable-line
|
||||
});
|
||||
}, 'octicon octicon-plus');
|
||||
|
||||
this.$result.on('click', '.btn.zoom-view', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var name = $(e.target).attr('data-name');
|
||||
name = decodeURIComponent(name);
|
||||
|
||||
this.quick_view.set_title(name);
|
||||
let values = this.data_dict[name];
|
||||
this.quick_view.set_values(values);
|
||||
|
||||
let fields = [];
|
||||
|
||||
this.quick_view.show();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
setup_like() {
|
||||
if(this.setup_like_done) return;
|
||||
this.setup_like_done = 1;
|
||||
this.$result.on('click', '.btn.like-button', (e) => {
|
||||
if($(e.target).hasClass('changing')) return;
|
||||
$(e.target).addClass('changing');
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var name = $(e.target).attr('data-name');
|
||||
name = decodeURIComponent(name);
|
||||
let values = this.data_dict[name];
|
||||
|
||||
let heart = $(e.target);
|
||||
if(heart.hasClass('like-button')) {
|
||||
heart = $(e.target).find('.octicon');
|
||||
}
|
||||
|
||||
let remove = 1;
|
||||
|
||||
if(heart.hasClass('liked')) {
|
||||
// unlike
|
||||
heart.removeClass('liked');
|
||||
} else {
|
||||
// like
|
||||
remove = 0;
|
||||
heart.addClass('liked');
|
||||
}
|
||||
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.update_wishlist_item',
|
||||
args: {
|
||||
item_name: values.hub_item_code,
|
||||
remove: remove
|
||||
},
|
||||
callback: (r) => {
|
||||
let message = __("Added to Favourites");
|
||||
if(remove) {
|
||||
message = __("Removed from Favourites");
|
||||
}
|
||||
frappe.show_alert(message);
|
||||
},
|
||||
freeze: true
|
||||
});
|
||||
|
||||
$(e.target).removeClass('changing');
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.hub.ItemListing = class ItemListing extends erpnext.hub.HubListing {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
this.show();
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Hub Item';
|
||||
this.page_title = __('Products');
|
||||
this.fields = ['name', 'hub_item_code', 'image', 'item_name', 'item_code', 'company_name', 'description', 'country'];
|
||||
this.filters = [];
|
||||
}
|
||||
|
||||
render() {
|
||||
this.data_dict = {};
|
||||
this.render_image_view();
|
||||
|
||||
this.setup_quick_view();
|
||||
this.setup_like();
|
||||
}
|
||||
|
||||
bootstrap_data(response) {
|
||||
let companies = response.companies.map(d => d.name);
|
||||
this.custom_filter_configs = [
|
||||
{
|
||||
fieldtype: 'Autocomplete',
|
||||
label: __('Select Company'),
|
||||
condition: 'like',
|
||||
fieldname: 'company_name',
|
||||
options: companies
|
||||
},
|
||||
{
|
||||
fieldtype: 'Link',
|
||||
label: __('Select Country'),
|
||||
options: 'Country',
|
||||
condition: 'like',
|
||||
fieldname: 'country'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
prepareFormFields() {
|
||||
let fieldnames = ['item_name', 'description', 'company_name', 'country'];
|
||||
this.formFields = this.meta.fields
|
||||
.filter(field => fieldnames.includes(field.fieldname))
|
||||
.map(field => {
|
||||
let {
|
||||
label,
|
||||
fieldname,
|
||||
fieldtype,
|
||||
} = field;
|
||||
let read_only = 1;
|
||||
return {
|
||||
label,
|
||||
fieldname,
|
||||
fieldtype,
|
||||
read_only,
|
||||
};
|
||||
});
|
||||
|
||||
this.formFields.unshift({
|
||||
label: 'image',
|
||||
fieldname: 'image',
|
||||
fieldtype: 'Attach Image'
|
||||
});
|
||||
}
|
||||
|
||||
setup_side_bar() {
|
||||
super.setup_side_bar();
|
||||
|
||||
let $pitch = $(`<div class="border" style="
|
||||
margin-top: 10px;
|
||||
padding: 0px 10px;
|
||||
border-radius: 3px;
|
||||
">
|
||||
<h5>Sell on HubMarket</h5>
|
||||
<p>Over 2000 products listed. Register your company to start selling.</p>
|
||||
</div>`);
|
||||
|
||||
this.sidebar.$sidebar.append($pitch);
|
||||
|
||||
this.category_tree = new frappe.ui.Tree({
|
||||
parent: this.sidebar.$sidebar,
|
||||
label: 'All Categories',
|
||||
expandable: true,
|
||||
|
||||
args: {parent: this.current_category},
|
||||
method: 'erpnext.hub_node.get_categories',
|
||||
on_click: (node) => {
|
||||
this.update_category(node.label);
|
||||
}
|
||||
});
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: __('Companies'),
|
||||
on_click: () => frappe.set_route('Hub', 'Company')
|
||||
}, undefined, true);
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: this.hub_settings.company,
|
||||
on_click: () => frappe.set_route('Form', 'Company', this.hub_settings.company)
|
||||
}, __("Account"));
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: __("Favourites"),
|
||||
on_click: () => frappe.set_route('Hub', 'Favourites')
|
||||
}, __("Account"));
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: __("Settings"),
|
||||
on_click: () => frappe.set_route('Form', 'Hub Settings')
|
||||
}, __("Account"));
|
||||
}
|
||||
|
||||
update_category(label) {
|
||||
this.current_category = (label=='All Categories') ? undefined : label;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
get_filters_for_args() {
|
||||
if(!this.filter_area) return;
|
||||
let filters = {};
|
||||
this.filter_area.get().forEach(f => {
|
||||
let field = f[1] !== 'name' ? f[1] : 'item_name';
|
||||
filters[field] = [f[2], f[3]];
|
||||
});
|
||||
if(this.current_category) {
|
||||
filters['hub_category'] = this.current_category;
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
update_data(r) {
|
||||
super.update_data(r);
|
||||
|
||||
this.data_dict = {};
|
||||
this.data.map(d => {
|
||||
this.data_dict[d.hub_item_code] = d;
|
||||
});
|
||||
}
|
||||
|
||||
item_html(item) {
|
||||
item._name = encodeURI(item.name);
|
||||
const encoded_name = item._name;
|
||||
const title = strip_html(item[this.meta.title_field || 'name']);
|
||||
const _class = !item[this.imageFieldName] ? 'no-image' : '';
|
||||
const route = `#Hub/Item/${item.hub_item_code}`;
|
||||
const company_name = item['company_name'];
|
||||
|
||||
const reviewLength = (item.reviews || []).length;
|
||||
const ratingAverage = reviewLength
|
||||
? item.reviews
|
||||
.map(r => r.rating)
|
||||
.reduce((a, b) => a + b, 0)/reviewLength
|
||||
: -1;
|
||||
|
||||
let ratingHtml = ``;
|
||||
|
||||
for(var i = 0; i < 5; i++) {
|
||||
let starClass = 'fa-star';
|
||||
if(i >= ratingAverage) starClass = 'fa-star-o';
|
||||
ratingHtml += `<i class='fa fa-fw ${starClass} star-icon' data-index=${i}></i>`;
|
||||
}
|
||||
|
||||
let item_html = `
|
||||
<div class="image-view-item">
|
||||
<div class="image-view-header">
|
||||
<div class="list-row-col list-subject ellipsis level">
|
||||
<span class="level-item bold ellipsis" title="McGuffin">
|
||||
<a href="${route}">${title}</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-muted small" style="margin: 5px 0px;">
|
||||
${ratingHtml}
|
||||
(${reviewLength})
|
||||
</div>
|
||||
<div class="list-row-col">
|
||||
<a href="${'#Hub/Company/'+company_name}"><p>${ company_name }</p></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-view-body">
|
||||
<a data-name="${encoded_name}"
|
||||
title="${encoded_name}"
|
||||
href="${route}"
|
||||
>
|
||||
<div class="image-field ${_class}"
|
||||
data-name="${encoded_name}"
|
||||
>
|
||||
<button class="btn btn-default zoom-view" data-name="${encoded_name}">
|
||||
<i class="octicon octicon-eye" data-name="${encoded_name}"></i>
|
||||
</button>
|
||||
<button class="btn btn-default like-button" data-name="${encoded_name}">
|
||||
<i class="octicon octicon-heart" data-name="${encoded_name}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`;
|
||||
|
||||
return item_html;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
erpnext.hub.Favourites = class Favourites extends erpnext.hub.ItemListing {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
this.show();
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Hub Item';
|
||||
this.page_title = __('Favourites');
|
||||
this.fields = ['name', 'hub_item_code', 'image', 'item_name', 'item_code', 'company_name', 'description', 'country'];
|
||||
this.filters = [];
|
||||
this.method = 'erpnext.hub_node.get_item_favourites';
|
||||
}
|
||||
|
||||
setup_filter_area() { }
|
||||
|
||||
setup_sort_selector() { }
|
||||
|
||||
// setupHe
|
||||
|
||||
getHeaderHtml() {
|
||||
return '';
|
||||
}
|
||||
|
||||
get_args() {
|
||||
return {
|
||||
start: this.start,
|
||||
limit: this.page_length,
|
||||
order_by: this.order_by,
|
||||
fields: this.fields
|
||||
};
|
||||
}
|
||||
|
||||
bootstrap_data(response) { }
|
||||
|
||||
prepareFormFields() { }
|
||||
|
||||
setup_side_bar() {
|
||||
this.sidebar = new frappe.ui.Sidebar({
|
||||
wrapper: this.page.wrapper.find('.layout-side-section'),
|
||||
css_class: 'hub-sidebar'
|
||||
});
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: __('Back to Products'),
|
||||
on_click: () => frappe.set_route('Hub', 'Item')
|
||||
});
|
||||
}
|
||||
|
||||
update_category(label) {
|
||||
this.current_category = (label=='All Categories') ? undefined : label;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
get_filters_for_args() {
|
||||
if(!this.filter_area) return;
|
||||
let filters = {};
|
||||
this.filter_area.get().forEach(f => {
|
||||
let field = f[1] !== 'name' ? f[1] : 'item_name';
|
||||
filters[field] = [f[2], f[3]];
|
||||
});
|
||||
if(this.current_category) {
|
||||
filters['hub_category'] = this.current_category;
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
update_data(r) {
|
||||
super.update_data(r);
|
||||
|
||||
this.data_dict = {};
|
||||
this.data.map(d => {
|
||||
this.data_dict[d.hub_item_code] = d;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
erpnext.hub.CompanyListing = class CompanyListing extends erpnext.hub.HubListing {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
this.show();
|
||||
}
|
||||
|
||||
render() {
|
||||
this.data_dict = {};
|
||||
this.render_image_view();
|
||||
}
|
||||
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Hub Company';
|
||||
this.page_title = __('Companies');
|
||||
this.fields = ['company_logo', 'name', 'site_name', 'seller_city', 'seller_description', 'seller', 'country', 'company_name'];
|
||||
this.filters = [];
|
||||
this.custom_filter_configs = [
|
||||
{
|
||||
fieldtype: 'Link',
|
||||
label: 'Country',
|
||||
options: 'Country',
|
||||
condition: 'like',
|
||||
fieldname: 'country'
|
||||
}
|
||||
];
|
||||
this.imageFieldName = 'company_logo';
|
||||
}
|
||||
|
||||
setup_side_bar() {
|
||||
this.sidebar = new frappe.ui.Sidebar({
|
||||
wrapper: this.page.wrapper.find('.layout-side-section'),
|
||||
css_class: 'hub-sidebar'
|
||||
});
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: __('Back to Products'),
|
||||
on_click: () => frappe.set_route('Hub', 'Item')
|
||||
});
|
||||
}
|
||||
|
||||
get_filters_for_args() {
|
||||
let filters = {};
|
||||
this.filter_area.get().forEach(f => {
|
||||
let field = f[1] !== 'name' ? f[1] : 'company_name';
|
||||
filters[field] = [f[2], f[3]];
|
||||
});
|
||||
return filters;
|
||||
}
|
||||
|
||||
item_html(company) {
|
||||
company._name = encodeURI(company.company_name);
|
||||
const encoded_name = company._name;
|
||||
const title = strip_html(company.company_name);
|
||||
const _class = !company[this.imageFieldName] ? 'no-image' : '';
|
||||
const company_name = company['company_name'];
|
||||
const route = `#Hub/Company/${company_name}`;
|
||||
|
||||
let image_html = company.company_logo ?
|
||||
`<img src="${company.company_logo}"><span class="helper"></span>` :
|
||||
`<div class="standard-image">${frappe.get_abbr(company.company_name)}</div>`;
|
||||
|
||||
let item_html = `
|
||||
<div class="image-view-item">
|
||||
<div class="image-view-header">
|
||||
<div class="list-row-col list-subject ellipsis level">
|
||||
<span class="level-item bold ellipsis" title="McGuffin">
|
||||
<a href="${route}">${title}</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-view-body">
|
||||
<a data-name="${encoded_name}"
|
||||
title="${encoded_name}"
|
||||
href="${route}">
|
||||
<div class="image-field ${_class}"
|
||||
data-name="${encoded_name}">
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`;
|
||||
|
||||
return item_html;
|
||||
}
|
||||
|
||||
};
|
@ -1,244 +0,0 @@
|
||||
frappe.provide('erpnext.hub');
|
||||
|
||||
erpnext.hub.HubListing = class HubListing extends frappe.views.BaseList {
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.page_title = __('Hub');
|
||||
this.method = 'erpnext.hub_node.get_list';
|
||||
|
||||
const route = frappe.get_route();
|
||||
this.page_name = route[1];
|
||||
}
|
||||
|
||||
setup_fields() {
|
||||
return this.get_meta()
|
||||
.then(r => {
|
||||
this.meta = r.message || this.meta;
|
||||
frappe.model.sync(this.meta);
|
||||
});
|
||||
}
|
||||
|
||||
get_meta() {
|
||||
return new Promise(resolve =>
|
||||
frappe.call('erpnext.hub_node.get_meta', {doctype: this.doctype}, resolve));
|
||||
}
|
||||
|
||||
set_breadcrumbs() { }
|
||||
|
||||
setup_side_bar() {
|
||||
this.sidebar = new frappe.ui.Sidebar({
|
||||
wrapper: this.page.wrapper.find('.layout-side-section'),
|
||||
css_class: 'hub-sidebar'
|
||||
});
|
||||
}
|
||||
|
||||
setup_sort_selector() { }
|
||||
|
||||
setup_view() { }
|
||||
|
||||
get_args() {
|
||||
return {
|
||||
doctype: this.doctype,
|
||||
start: this.start,
|
||||
limit: this.page_length,
|
||||
order_by: this.order_by,
|
||||
fields: this.fields,
|
||||
filters: this.get_filters_for_args()
|
||||
};
|
||||
}
|
||||
|
||||
update_data(r) {
|
||||
const data = r.message;
|
||||
|
||||
if (this.start === 0) {
|
||||
this.data = data;
|
||||
} else {
|
||||
this.data = this.data.concat(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
freeze(toggle) {
|
||||
this.$freeze.toggle(toggle);
|
||||
if (this.$freeze.find('.image-view-container').length) return;
|
||||
|
||||
const html = Array.from(new Array(4)).map(d => this.card_html({
|
||||
name: 'Loading...',
|
||||
item_name: 'Loading...'
|
||||
})).join('');
|
||||
|
||||
this.$freeze.html(`<div class="image-view-container border-top">${html}</div>`);
|
||||
}
|
||||
|
||||
render() {
|
||||
this.render_image_view();
|
||||
}
|
||||
|
||||
render_image_view() {
|
||||
let data = this.data;
|
||||
if (this.start === 0) {
|
||||
this.$result.html('<div class="image-view-container small padding-top">');
|
||||
data = this.data.slice(this.start);
|
||||
}
|
||||
|
||||
var html = data.map(this.card_html.bind(this)).join("");
|
||||
this.$result.find('.image-view-container').append(html);
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.hub.ItemListing = class ItemListing extends erpnext.hub.HubListing {
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Hub Item';
|
||||
this.fields = ['name', 'hub_item_code', 'image', 'item_name', 'item_code', 'company_name'];
|
||||
this.filters = [];
|
||||
this.custom_filter_configs = [
|
||||
{
|
||||
fieldtype: 'Data',
|
||||
label: 'Company',
|
||||
condition: 'like',
|
||||
fieldname: 'company_name',
|
||||
},
|
||||
{
|
||||
fieldtype: 'Link',
|
||||
label: 'Country',
|
||||
options: 'Country',
|
||||
condition: 'like',
|
||||
fieldname: 'country'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
setup_side_bar() {
|
||||
super.setup_side_bar();
|
||||
this.category_tree = new frappe.ui.Tree({
|
||||
parent: this.sidebar.$sidebar,
|
||||
label: 'All Categories',
|
||||
expandable: true,
|
||||
|
||||
args: {parent: this.current_category},
|
||||
method: 'erpnext.hub_node.get_categories',
|
||||
on_click: (node) => {
|
||||
this.update_category(node.label);
|
||||
}
|
||||
});
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: __('Companies'),
|
||||
on_click: () => frappe.set_route('Hub', 'Company')
|
||||
});
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: this.hub_settings.company,
|
||||
on_click: () => frappe.set_route('Form', 'Company', this.hub_settings.company)
|
||||
}, __("Account"));
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: __("My Orders"),
|
||||
on_click: () => frappe.set_route('List', 'Request for Quotation')
|
||||
}, __("Account"));
|
||||
}
|
||||
|
||||
update_category(label) {
|
||||
this.current_category = (label=='All Categories') ? undefined : label;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
get_filters_for_args() {
|
||||
let filters = {};
|
||||
this.filter_area.get().forEach(f => {
|
||||
let field = f[1] !== 'name' ? f[1] : 'item_name';
|
||||
filters[field] = [f[2], f[3]];
|
||||
});
|
||||
if(this.current_category) {
|
||||
filters['hub_category'] = this.current_category;
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
card_html(item) {
|
||||
item._name = encodeURI(item.name);
|
||||
const encoded_name = item._name;
|
||||
const title = strip_html(item['item_name' || 'item_code']);
|
||||
const company_name = item['company_name'];
|
||||
|
||||
const route = `#Hub/Item/${item.hub_item_code}`;
|
||||
|
||||
const image_html = item.image ?
|
||||
`<img src="${item.image}">
|
||||
<span class="helper"></span>` :
|
||||
`<div class="standard-image">${frappe.get_abbr(title)}</div>`;
|
||||
|
||||
return `
|
||||
<div class="hub-item-wrapper margin-bottom" style="width: 200px;">
|
||||
<a href="${route}">
|
||||
<div class="hub-item-image">
|
||||
<div class="img-wrapper" style="height: 200px; width: 200px">
|
||||
${ image_html }
|
||||
</div>
|
||||
</div>
|
||||
<div class="hub-item-title">
|
||||
<h5 class="bold">
|
||||
${ title }
|
||||
</h5>
|
||||
|
||||
</div>
|
||||
</a>
|
||||
<a href="${'#Hub/Company/'+company_name}"><p>${ company_name }</p></a>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
};
|
||||
|
||||
erpnext.hub.CompanyListing = class CompanyListing extends erpnext.hub.HubListing {
|
||||
setup_defaults() {
|
||||
super.setup_defaults();
|
||||
this.doctype = 'Hub Company';
|
||||
this.fields = ['company_logo', 'name', 'site_name', 'seller_city', 'seller_description', 'seller', 'country', 'company_name'];
|
||||
this.filters = [];
|
||||
this.custom_filter_configs = [
|
||||
{
|
||||
fieldtype: 'Link',
|
||||
label: 'Country',
|
||||
options: 'Country',
|
||||
condition: 'like',
|
||||
fieldname: 'country'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
get_filters_for_args() {
|
||||
let filters = {};
|
||||
this.filter_area.get().forEach(f => {
|
||||
let field = f[1] !== 'name' ? f[1] : 'company_name';
|
||||
filters[field] = [f[2], f[3]];
|
||||
});
|
||||
return filters;
|
||||
}
|
||||
|
||||
card_html(company) {
|
||||
company._name = encodeURI(company.name);
|
||||
const route = `#Hub/Company/${company.company_name}`;
|
||||
|
||||
let image_html = company.company_logo ?
|
||||
`<img src="${company.company_logo}"><span class="helper"></span>` :
|
||||
`<div class="standard-image">${frappe.get_abbr(company.company_name)}</div>`;
|
||||
|
||||
return `
|
||||
<div class="hub-item-wrapper margin-bottom" style="width: 200px;">
|
||||
<a href="${route}">
|
||||
<div class="hub-item-image">
|
||||
<div class="img-wrapper" style="height: 200px; width: 200px">
|
||||
${ image_html }
|
||||
</div>
|
||||
</div>
|
||||
<div class="hub-item-title">
|
||||
<h5 class="bold">
|
||||
${ company.company_name }
|
||||
</h5>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
};
|
@ -50,7 +50,7 @@ erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) {
|
||||
var currentIncrement = timestamp;
|
||||
var initialised = row ? true : false;
|
||||
var clicked = false;
|
||||
|
||||
var flag = true; // Alert only once
|
||||
// If row with not completed status, initialize timer with the time elapsed on click of 'Start Timer'.
|
||||
if (row) {
|
||||
initialised = true;
|
||||
@ -66,7 +66,7 @@ erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) {
|
||||
// New activity if no activities found
|
||||
var args = dialog.get_values();
|
||||
if(!args) return;
|
||||
if (!frm.doc.time_logs[0].activity_type) {
|
||||
if (frm.doc.time_logs.length <= 1 && !frm.doc.time_logs[0].activity_type && !frm.doc.time_logs[0].from_time) {
|
||||
frm.doc.time_logs = [];
|
||||
}
|
||||
row = frappe.model.add_child(frm.doc, "Timesheet Detail", "time_logs");
|
||||
@ -130,8 +130,15 @@ erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) {
|
||||
if (!$('.modal-dialog').is(':visible')) {
|
||||
reset();
|
||||
}
|
||||
if(hours > 99)
|
||||
if(hours > 99999)
|
||||
reset();
|
||||
if(cur_dialog && cur_dialog.get_value('expected_hours') > 0) {
|
||||
if(flag && (currentIncrement >= (cur_dialog.get_value('expected_hours') * 3600))) {
|
||||
frappe.utils.play_sound("alert");
|
||||
frappe.msgprint(__("Timer exceeded the given hours."));
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
$(".hours").text(hours < 10 ? ("0" + hours.toString()) : hours.toString());
|
||||
$(".minutes").text(minutes < 10 ? ("0" + minutes.toString()) : minutes.toString());
|
||||
$(".seconds").text(seconds < 10 ? ("0" + seconds.toString()) : seconds.toString());
|
||||
|
@ -23,6 +23,20 @@
|
||||
margin-top: -3px;
|
||||
}
|
||||
|
||||
.app-icon-svg {
|
||||
display: inline-block;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
border-radius: 16px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.app-icon-svg .hub-icon {
|
||||
height: 72px;
|
||||
width: 72px;
|
||||
}
|
||||
|
||||
.dashboard-list-item {
|
||||
background-color: inherit;
|
||||
padding: 5px 0px;
|
||||
|
@ -1,176 +1,171 @@
|
||||
@import "../../../../frappe/frappe/public/less/variables.less";
|
||||
|
||||
body[data-route^="Hub/"] {
|
||||
.freeze .image-view-container {
|
||||
.list-row-col {
|
||||
background-color: @light-bg;
|
||||
color: @light-bg;
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
color: @light-bg;
|
||||
}
|
||||
.hub-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.freeze {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.image-view-container {
|
||||
justify-content: space-around;
|
||||
}
|
||||
}
|
||||
|
||||
.img-wrapper {
|
||||
border: 1px solid #d1d8dd;
|
||||
border-radius: 3px;
|
||||
padding: 12px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
|
||||
.helper {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
/* hub */
|
||||
div[data-page-route="hub"] {
|
||||
.page-head {
|
||||
height: 80px;
|
||||
|
||||
.title-text {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.page-content {
|
||||
margin-top: 80px;
|
||||
}
|
||||
|
||||
.page-title h1 {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.account-details {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
[data-original-title="Search"] {
|
||||
float: right;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.hub-main-section {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.listing-body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.main-list-section {
|
||||
padding: 0;
|
||||
// border-right: 1px solid #d1d8dd;
|
||||
}
|
||||
|
||||
.side-list-section {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.item-list-header h3 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hub-item-page {
|
||||
|
||||
h2 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.item-header {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.item-page-image {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.title-content {
|
||||
flex: 3;
|
||||
|
||||
.description {
|
||||
margin: 30px 0px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-top: 30px;
|
||||
|
||||
.rfq-btn.disabled {
|
||||
background-color: #b1bdca;
|
||||
color: #fff;
|
||||
border-color: #b1bdca;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.company-items {
|
||||
margin-top: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.company-header {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.item-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.hub-item-wrapper {
|
||||
margin-bottom: 20px;
|
||||
.hub-page-title {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.img-wrapper {
|
||||
border: 1px solid @border-color;
|
||||
border: 1px solid #d1d8dd;
|
||||
border-radius: 3px;
|
||||
padding: 12px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.helper {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.standard-image {
|
||||
font-size: 72px;
|
||||
border: none;
|
||||
background-color: @light-bg;
|
||||
.tree {
|
||||
margin: 10px 0px;
|
||||
padding: 0px;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tree.with-skeleton.opened::before {
|
||||
left: 9px;
|
||||
top: 14px;
|
||||
height: calc(~"100% - 32px");
|
||||
}
|
||||
|
||||
.list-header-icon {
|
||||
width: 72px;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
margin: 10px;
|
||||
padding: 1px;
|
||||
border: 1px solid @border-color;
|
||||
height: 72px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.hub-item-title {
|
||||
.star-icon.fa-star {
|
||||
color: @indicator-orange;
|
||||
}
|
||||
|
||||
.octicon-heart.liked {
|
||||
color: @indicator-red;
|
||||
}
|
||||
|
||||
.margin-vertical-10 {
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
.margin-vertical-15 {
|
||||
margin: 15px 0px;
|
||||
}
|
||||
|
||||
.frappe-list .result {
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.frappe-control[data-fieldtype="Attach Image"] {
|
||||
width: 140px;
|
||||
height: 180px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.frappe-control[data-fieldtype="Attach Image"] .form-group {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.frappe-control[data-fieldtype="Attach Image"] .clearfix {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.missing-image {
|
||||
display: block;
|
||||
position: relative;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #d1d8dd;
|
||||
border-radius: 6px;
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.missing-image .octicon {
|
||||
position: relative;
|
||||
top: 50%;
|
||||
transform: translate(0px, -50%);
|
||||
-webkit-transform: translate(0px, -50%);
|
||||
}
|
||||
.attach-image-display {
|
||||
display: block;
|
||||
position: relative;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.img-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 2px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
border: 1px solid #d1d8dd;
|
||||
border-radius: 6px;
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.img-overlay {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #777777;
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
opacity: 0;
|
||||
}
|
||||
.img-overlay:hover {
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.image-view-container {
|
||||
.image-view-body {
|
||||
&:hover .like-button {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
padding-left: 0;
|
||||
padding-top: 0;
|
||||
margin-bottom: 10px;
|
||||
.like-button {
|
||||
bottom: 10px !important;
|
||||
left: 10px !important;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
opacity: 0;
|
||||
font-size: 16px;
|
||||
color: @text-color;
|
||||
position: absolute;
|
||||
|
||||
// show zoom button on mobile devices
|
||||
@media (max-width: @screen-xs) {
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.image-view-body:hover .like-button {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.rating-area .star-icon {
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
@ -180,7 +180,11 @@ def make_custom_fields():
|
||||
'Sales Invoice Item': [hsn_sac_field],
|
||||
'Purchase Order Item': [hsn_sac_field],
|
||||
'Purchase Receipt Item': [hsn_sac_field],
|
||||
'Purchase Invoice Item': [hsn_sac_field]
|
||||
'Purchase Invoice Item': [hsn_sac_field],
|
||||
'Employee': [
|
||||
dict(fieldname='ifsc_code', label='IFSC Code',
|
||||
fieldtype='Data', insert_after='bank_ac_no', print_hide=1,
|
||||
depends_on='eval:doc.salary_mode == "Bank"') ]
|
||||
}
|
||||
|
||||
create_custom_fields(custom_fields)
|
||||
|
@ -64,7 +64,7 @@ def get_itemised_tax_breakup_data(doc):
|
||||
def set_place_of_supply(doc, method):
|
||||
if not frappe.get_meta('Address').has_field('gst_state'): return
|
||||
|
||||
if doc.doctype == "Sales Invoice":
|
||||
if doc.doctype in ("Sales Invoice", "Delivery Note"):
|
||||
address_name = doc.shipping_address_name or doc.customer_address
|
||||
elif doc.doctype == "Purchase Invoice":
|
||||
address_name = doc.shipping_address or doc.supplier_address
|
||||
|
@ -587,6 +587,10 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
|
||||
"Sales Team": {
|
||||
"doctype": "Sales Team",
|
||||
"add_if_empty": True
|
||||
},
|
||||
"Payment Schedule": {
|
||||
"doctype": "Payment Schedule",
|
||||
"add_if_empty": True
|
||||
}
|
||||
}, target_doc, postprocess, ignore_permissions=ignore_permissions)
|
||||
|
||||
|
@ -8,18 +8,13 @@ import unittest
|
||||
from erpnext.selling.doctype.sales_order.sales_order \
|
||||
import make_material_request, make_delivery_note, make_sales_invoice, WarehouseRequired
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
from frappe.tests.test_permissions import set_user_permission_doctypes
|
||||
from erpnext.selling.doctype.sales_order.sales_order import make_work_orders
|
||||
import json
|
||||
|
||||
|
||||
class TestSalesOrder(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
frappe.set_user("Administrator")
|
||||
|
||||
for role in ("Stock User", "Sales User"):
|
||||
set_user_permission_doctypes(doctypes="Sales Order", role=role,
|
||||
apply_user_permissions=0, user_permission_doctypes=None)
|
||||
pass
|
||||
|
||||
def test_make_material_request(self):
|
||||
so = make_sales_order(do_not_submit=True)
|
||||
@ -259,10 +254,6 @@ class TestSalesOrder(unittest.TestCase):
|
||||
existing_reserved_qty_item2 + 20)
|
||||
|
||||
def test_warehouse_user(self):
|
||||
for role in ("Stock User", "Sales User"):
|
||||
set_user_permission_doctypes(doctypes="Sales Order", role=role,
|
||||
apply_user_permissions=1, user_permission_doctypes=["Warehouse"])
|
||||
|
||||
frappe.permissions.add_user_permission("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com")
|
||||
frappe.permissions.add_user_permission("Warehouse", "_Test Warehouse 2 - _TC1", "test2@example.com")
|
||||
frappe.permissions.add_user_permission("Company", "_Test Company 1", "test2@example.com")
|
||||
|
@ -886,9 +886,11 @@ class POSCart {
|
||||
const is_stock_item = this.get_item_details(item.item_code).is_stock_item;
|
||||
const rate = format_currency(item.rate, this.frm.doc.currency);
|
||||
const indicator_class = (!is_stock_item || item.actual_qty >= item.qty) ? 'green' : 'red';
|
||||
const batch_no = item.batch_no || '';
|
||||
|
||||
return `
|
||||
<div class="list-item indicator ${indicator_class}" data-item-code="${item.item_code}"
|
||||
data-batch-no="${item.batch_no}" title="Item: ${item.item_name} Available Qty: ${item.actual_qty}">
|
||||
data-batch-no="${batch_no}" title="Item: ${item.item_name} Available Qty: ${item.actual_qty}">
|
||||
<div class="item-name list-item__content list-item__content--flex-1.5 ellipsis">
|
||||
${item.item_name}
|
||||
</div>
|
||||
|
@ -85,7 +85,7 @@ def delete_lead_addresses(company_name):
|
||||
in ({leads})""".format(leads=",".join(leads)))
|
||||
|
||||
if addresses:
|
||||
addresses = ["'%s'"%addr for addr in addresses]
|
||||
addresses = ["'%s'"%frappe.db.escape(addr) for addr in addresses]
|
||||
|
||||
frappe.db.sql("""delete from tabAddress where name in ({addresses}) and
|
||||
name not in (select distinct dl1.parent from `tabDynamic Link` dl1
|
||||
|
@ -25,3 +25,6 @@ def get_parent_customer_groups(customer_group):
|
||||
return frappe.db.sql("""select name from `tabCustomer Group`
|
||||
where lft <= %s and rgt >= %s
|
||||
order by lft asc""", (lft, rgt), as_dict=True)
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Customer Group", ["lft", "rgt"])
|
@ -33,3 +33,6 @@ class SalesPerson(NestedSet):
|
||||
|
||||
if sales_person and sales_person != self.name:
|
||||
frappe.throw(_("Another Sales Person {0} exists with the same Employee id").format(sales_person))
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Sales Person", ["lft", "rgt"])
|
@ -22,3 +22,5 @@ class Territory(NestedSet):
|
||||
super(Territory, self).on_update()
|
||||
self.validate_one_root()
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Territory", ["lft", "rgt"])
|
@ -27,7 +27,6 @@ def set_default_settings(args):
|
||||
|
||||
domain_settings = frappe.get_single('Domain Settings')
|
||||
domain_settings.set_active_domains(args.get('domains'))
|
||||
domain_settings.save()
|
||||
|
||||
stock_settings = frappe.get_doc("Stock Settings")
|
||||
stock_settings.item_naming_by = "Item Code"
|
||||
|
@ -15,33 +15,39 @@ def get_warehouse_account_map():
|
||||
if not frappe.flags.warehouse_account_map or frappe.flags.in_test:
|
||||
warehouse_account = frappe._dict()
|
||||
|
||||
for d in frappe.get_all('Warehouse', filters = {"is_group": 0},
|
||||
fields = ["name", "account", "parent_warehouse", "company"]):
|
||||
for d in frappe.get_all('Warehouse',
|
||||
fields = ["name", "account", "parent_warehouse", "company"],
|
||||
order_by="lft, rgt"):
|
||||
if not d.account:
|
||||
d.account = get_warehouse_account(d.name, d.company)
|
||||
d.account = get_warehouse_account(d, warehouse_account)
|
||||
|
||||
if d.account:
|
||||
d.account_currency = frappe.db.get_value('Account', d.account, 'account_currency')
|
||||
d.account_currency = frappe.db.get_value('Account', d.account, 'account_currency', cache=True)
|
||||
warehouse_account.setdefault(d.name, d)
|
||||
|
||||
|
||||
frappe.flags.warehouse_account_map = warehouse_account
|
||||
|
||||
return frappe.flags.warehouse_account_map
|
||||
|
||||
def get_warehouse_account(warehouse, company):
|
||||
lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"])
|
||||
account = frappe.db.sql("""
|
||||
select
|
||||
account from `tabWarehouse`
|
||||
where
|
||||
lft <= %s and rgt >= %s and company = %s
|
||||
and account is not null and ifnull(account, '') !=''
|
||||
order by lft desc limit 1""", (lft, rgt, company), as_list=1)
|
||||
def get_warehouse_account(warehouse, warehouse_account=None):
|
||||
account = warehouse.account
|
||||
if not account and warehouse.parent_warehouse:
|
||||
if warehouse_account:
|
||||
account = warehouse_account.get(warehouse.parent_warehouse).account
|
||||
else:
|
||||
account = frappe.db.sql("""
|
||||
select
|
||||
account from `tabWarehouse`
|
||||
where
|
||||
lft <= %s and rgt >= %s and company = %s
|
||||
and account is not null and ifnull(account, '') !=''
|
||||
order by lft desc limit 1""", (warehouse.lft, warehouse.rgt, warehouse.company), as_list=1)
|
||||
|
||||
account = account[0][0] if account else None
|
||||
|
||||
account = account[0][0] if account else None
|
||||
|
||||
if not account:
|
||||
account = get_company_default_inventory_account(company)
|
||||
|
||||
account = get_company_default_inventory_account(warehouse.company)
|
||||
|
||||
return account
|
||||
|
||||
def get_company_default_inventory_account(company):
|
||||
|
@ -9,7 +9,7 @@ import googlemaps
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils.user import get_user_fullname
|
||||
from frappe.utils import getdate
|
||||
from frappe.utils import getdate, cstr
|
||||
from frappe.integrations.doctype.google_maps.google_maps import round_timedelta
|
||||
from frappe.integrations.doctype.google_maps.google_maps import format_address
|
||||
|
||||
@ -141,40 +141,33 @@ def calculate_time_matrix(name):
|
||||
@frappe.whitelist()
|
||||
def notify_customers(docname, date, driver, vehicle, sender_email, delivery_notification):
|
||||
sender_name = get_user_fullname(sender_email)
|
||||
delivery_stops = frappe.get_all('Delivery Stop', {"parent": docname})
|
||||
attachments = []
|
||||
|
||||
for delivery_stop in delivery_stops:
|
||||
delivery_stop_info = frappe.db.get_value(
|
||||
"Delivery Stop",
|
||||
delivery_stop.name,
|
||||
["notified_by_email", "estimated_arrival", "details", "contact", "delivery_note"],
|
||||
as_dict=1)
|
||||
contact_info = frappe.db.get_value("Contact", delivery_stop_info.contact,
|
||||
parent_doc = frappe.get_doc('Delivery Trip', docname)
|
||||
args = parent_doc.as_dict()
|
||||
|
||||
for delivery_stop in parent_doc.delivery_stops:
|
||||
contact_info = frappe.db.get_value("Contact", delivery_stop.contact,
|
||||
["first_name", "last_name", "email_id", "gender"], as_dict=1)
|
||||
|
||||
if delivery_stop_info.delivery_note:
|
||||
args.update(delivery_stop.as_dict())
|
||||
args.update(contact_info)
|
||||
|
||||
if delivery_stop.delivery_note:
|
||||
default_print_format = frappe.get_meta('Delivery Note').default_print_format
|
||||
attachments = frappe.attach_print('Delivery Note',
|
||||
delivery_stop_info.delivery_note,
|
||||
delivery_stop.delivery_note,
|
||||
file_name="Delivery Note",
|
||||
print_format=default_print_format or "Standard")
|
||||
|
||||
if not delivery_stop_info.notified_by_email and contact_info.email_id:
|
||||
if not delivery_stop.notified_by_email and contact_info.email_id:
|
||||
driver_info = frappe.db.get_value("Driver", driver, ["full_name", "cell_number"], as_dict=1)
|
||||
sender_designation = frappe.db.get_value("Employee", sender_email, ["designation"])
|
||||
|
||||
estimated_arrival = str(delivery_stop_info.estimated_arrival)[:-3]
|
||||
estimated_arrival = cstr(delivery_stop.estimated_arrival)[:-3]
|
||||
email_template = frappe.get_doc("Standard Reply", delivery_notification)
|
||||
message = frappe.render_template(
|
||||
email_template.response,
|
||||
dict(contact_info=contact_info, sender_name=sender_name,
|
||||
details=delivery_stop_info.details,
|
||||
estimated_arrival=estimated_arrival,
|
||||
date=getdate(date).strftime('%d.%m.%y'), vehicle=vehicle,
|
||||
driver_info=driver_info,
|
||||
sender_designation=sender_designation)
|
||||
)
|
||||
message = frappe.render_template(email_template.response, args)
|
||||
|
||||
frappe.sendmail(
|
||||
recipients=contact_info.email_id,
|
||||
sender=sender_email,
|
||||
|
@ -532,7 +532,7 @@ class Item(WebsiteGenerator):
|
||||
|
||||
def on_trash(self):
|
||||
super(Item, self).on_trash()
|
||||
frappe.db.sql("""delete from tabBin where item_code=%s""", self.item_code)
|
||||
frappe.db.sql("""delete from tabBin where item_code=%s""", self.name)
|
||||
frappe.db.sql("delete from `tabItem Price` where item_code=%s", self.name)
|
||||
for variant_of in frappe.get_all("Item", filters={"variant_of": self.name}):
|
||||
frappe.delete_doc("Item", variant_of.name)
|
||||
|
@ -12,7 +12,6 @@ from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import StockFre
|
||||
from erpnext.stock.stock_ledger import get_previous_sle
|
||||
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
|
||||
from erpnext.stock.doctype.item.test_item import set_item_variant_settings, make_item_variant, create_item
|
||||
from frappe.tests.test_permissions import set_user_permission_doctypes
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry import move_sample_to_retention_warehouse
|
||||
@ -35,10 +34,6 @@ class TestStockEntry(unittest.TestCase):
|
||||
frappe.set_user("Administrator")
|
||||
set_perpetual_inventory(0)
|
||||
|
||||
for role in ("Stock User", "Sales User"):
|
||||
set_user_permission_doctypes(doctypes="Stock Entry", role=role,
|
||||
apply_user_permissions=0, user_permission_doctypes=None)
|
||||
|
||||
def test_fifo(self):
|
||||
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
|
||||
item_code = "_Test Item 2"
|
||||
@ -485,10 +480,6 @@ class TestStockEntry(unittest.TestCase):
|
||||
|
||||
# permission tests
|
||||
def test_warehouse_user(self):
|
||||
for role in ("Stock User", "Sales User"):
|
||||
set_user_permission_doctypes(doctypes="Stock Entry", role=role,
|
||||
apply_user_permissions=1, user_permission_doctypes=["Warehouse"])
|
||||
|
||||
frappe.defaults.add_default("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com", "User Permission")
|
||||
frappe.defaults.add_default("Warehouse", "_Test Warehouse 2 - _TC1", "test2@example.com", "User Permission")
|
||||
test_user = frappe.get_doc("User", "test@example.com")
|
||||
@ -619,10 +610,10 @@ class TestStockEntry(unittest.TestCase):
|
||||
def test_retain_sample(self):
|
||||
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||
from erpnext.stock.doctype.batch.batch import get_batch_qty
|
||||
|
||||
|
||||
create_warehouse("Test Warehouse for Sample Retention")
|
||||
frappe.db.set_value("Stock Settings", None, "sample_retention_warehouse", "Test Warehouse for Sample Retention - _TC")
|
||||
|
||||
|
||||
item = frappe.new_doc("Item")
|
||||
item.item_code = "Retain Sample Item"
|
||||
item.item_name = "Retain Sample Item"
|
||||
@ -667,7 +658,7 @@ class TestStockEntry(unittest.TestCase):
|
||||
|
||||
qty_in_usable_warehouse = get_batch_qty(receipt_entry.get("items")[0].batch_no, "_Test Warehouse - _TC", "_Test Item")
|
||||
qty_in_retention_warehouse = get_batch_qty(receipt_entry.get("items")[0].batch_no, "Test Warehouse for Sample Retention - _TC", "_Test Item")
|
||||
|
||||
|
||||
self.assertEqual(qty_in_usable_warehouse, 36)
|
||||
self.assertEqual(qty_in_retention_warehouse, 4)
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
from frappe.utils import cint, validate_email_add
|
||||
from frappe.utils import cint
|
||||
from frappe import throw, _
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
from erpnext.stock import get_warehouse_account
|
||||
@ -22,7 +22,7 @@ class Warehouse(NestedSet):
|
||||
|
||||
def onload(self):
|
||||
'''load account name for General Ledger Report'''
|
||||
account = self.account or get_warehouse_account(self.name, self.company)
|
||||
account = self.account or get_warehouse_account(self)
|
||||
|
||||
if account:
|
||||
self.set_onload('account', account)
|
||||
|
@ -40,7 +40,9 @@ def get_data(item):
|
||||
name = item_dict["variant_name"]
|
||||
|
||||
for d in attribute_list:
|
||||
item_dict[d] = attr_val_map[name][d]
|
||||
attr_dict = attr_val_map[name]
|
||||
if attr_dict and attr_dict.get(d):
|
||||
item_dict[d] = attr_val_map[name][d]
|
||||
|
||||
item_dict["Open Orders"] = order_count_map.get(name) or 0
|
||||
|
||||
|
@ -7,8 +7,9 @@ from frappe import _
|
||||
|
||||
def execute(filters=None):
|
||||
columns = get_columns()
|
||||
sl_entries = get_stock_ledger_entries(filters)
|
||||
item_details = get_item_details(filters)
|
||||
item_conditions = get_item_conditions(filters)
|
||||
item_details = get_item_details(filters, item_conditions)
|
||||
sl_entries = get_stock_ledger_entries(filters, item_conditions, item_details)
|
||||
opening_row = get_opening_balance(filters, columns)
|
||||
|
||||
data = []
|
||||
@ -52,7 +53,12 @@ def get_columns():
|
||||
|
||||
return columns
|
||||
|
||||
def get_stock_ledger_entries(filters):
|
||||
def get_stock_ledger_entries(filters, item_conditions, item_details):
|
||||
item_conditions_sql = ''
|
||||
if item_conditions:
|
||||
items = ['"' + frappe.db.escape(i) + '"' for i in item_details.keys()]
|
||||
if items:
|
||||
item_conditions_sql = 'and sle.item_code in ({})'.format(', '.join(items))
|
||||
return frappe.db.sql("""select concat_ws(" ", posting_date, posting_time) as date,
|
||||
item_code, warehouse, actual_qty, qty_after_transaction, incoming_rate, valuation_rate,
|
||||
stock_value, voucher_type, voucher_no, batch_no, serial_no, company, project
|
||||
@ -60,14 +66,18 @@ def get_stock_ledger_entries(filters):
|
||||
where company = %(company)s and
|
||||
posting_date between %(from_date)s and %(to_date)s
|
||||
{sle_conditions}
|
||||
{item_conditions_sql}
|
||||
order by posting_date asc, posting_time asc, name asc"""\
|
||||
.format(sle_conditions=get_sle_conditions(filters)), filters, as_dict=1)
|
||||
.format(
|
||||
sle_conditions=get_sle_conditions(filters),
|
||||
item_conditions_sql = item_conditions_sql
|
||||
), filters, as_dict=1)
|
||||
|
||||
def get_item_details(filters):
|
||||
def get_item_details(filters, item_conditions):
|
||||
item_details = {}
|
||||
for item in frappe.db.sql("""select name, item_name, description, item_group,
|
||||
brand, stock_uom from `tabItem` item {item_conditions}"""\
|
||||
.format(item_conditions=get_item_conditions(filters)), filters, as_dict=1):
|
||||
.format(item_conditions=item_conditions), filters, as_dict=1):
|
||||
item_details.setdefault(item.name, item)
|
||||
|
||||
return item_details
|
||||
@ -85,10 +95,6 @@ def get_item_conditions(filters):
|
||||
|
||||
def get_sle_conditions(filters):
|
||||
conditions = []
|
||||
item_conditions=get_item_conditions(filters)
|
||||
if item_conditions:
|
||||
conditions.append("""sle.item_code in (select item.name from tabItem item
|
||||
{item_conditions})""".format(item_conditions=item_conditions))
|
||||
if filters.get("warehouse"):
|
||||
warehouse_condition = get_warehouse_condition(filters.get("warehouse"))
|
||||
if warehouse_condition:
|
||||
|
@ -444,7 +444,7 @@ def get_valuation_rate(item_code, warehouse, voucher_type, voucher_no,
|
||||
last_valuation_rate = frappe.db.sql("""select valuation_rate
|
||||
from `tabStock Ledger Entry`
|
||||
where item_code = %s and warehouse = %s
|
||||
and valuation_rate > 0
|
||||
and valuation_rate >= 0
|
||||
order by posting_date desc, posting_time desc, name desc limit 1""", (item_code, warehouse))
|
||||
|
||||
if not last_valuation_rate:
|
||||
|