mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-14 01:20:41 +00:00
Merge branch 'develop' into e-commerce-refactor-develop
This commit is contained in:
@@ -12,6 +12,10 @@ frappe.ui.form.on("Company", {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
frm.call('check_if_transactions_exist').then(r => {
|
||||
frm.toggle_enable("default_currency", (!r.message));
|
||||
});
|
||||
},
|
||||
setup: function(frm) {
|
||||
erpnext.company.setup_queries(frm);
|
||||
@@ -75,21 +79,15 @@ frappe.ui.form.on("Company", {
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
if(!frm.doc.__islocal) {
|
||||
frm.doc.abbr && frm.set_df_property("abbr", "read_only", 1);
|
||||
frm.set_df_property("parent_company", "read_only", 1);
|
||||
disbale_coa_fields(frm);
|
||||
}
|
||||
frm.toggle_display('address_html', !frm.is_new());
|
||||
|
||||
frm.toggle_display('address_html', !frm.doc.__islocal);
|
||||
if(!frm.doc.__islocal) {
|
||||
if (!frm.is_new()) {
|
||||
frm.doc.abbr && frm.set_df_property("abbr", "read_only", 1);
|
||||
disbale_coa_fields(frm);
|
||||
frappe.contacts.render_address_and_contact(frm);
|
||||
|
||||
frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Company'}
|
||||
|
||||
frm.toggle_enable("default_currency", (frm.doc.__onload &&
|
||||
!frm.doc.__onload.transactions_exist));
|
||||
|
||||
if (frappe.perm.has_perm("Cost Center", 0, 'read')) {
|
||||
frm.add_custom_button(__('Cost Centers'), function() {
|
||||
frappe.set_route('Tree', 'Cost Center', {'company': frm.doc.name});
|
||||
|
||||
@@ -22,8 +22,8 @@ class Company(NestedSet):
|
||||
|
||||
def onload(self):
|
||||
load_address_and_contact(self, "company")
|
||||
self.get("__onload")["transactions_exist"] = self.check_if_transactions_exist()
|
||||
|
||||
@frappe.whitelist()
|
||||
def check_if_transactions_exist(self):
|
||||
exists = False
|
||||
for doctype in ["Sales Invoice", "Delivery Note", "Sales Order", "Quotation",
|
||||
@@ -47,6 +47,7 @@ class Company(NestedSet):
|
||||
self.validate_perpetual_inventory()
|
||||
self.validate_perpetual_inventory_for_non_stock_items()
|
||||
self.check_country_change()
|
||||
self.check_parent_changed()
|
||||
self.set_chart_of_accounts()
|
||||
self.validate_parent_company()
|
||||
|
||||
@@ -130,6 +131,10 @@ class Company(NestedSet):
|
||||
self.name in frappe.local.enable_perpetual_inventory:
|
||||
frappe.local.enable_perpetual_inventory[self.name] = self.enable_perpetual_inventory
|
||||
|
||||
if frappe.flags.parent_company_changed:
|
||||
from frappe.utils.nestedset import rebuild_tree
|
||||
rebuild_tree("Company", "parent_company")
|
||||
|
||||
frappe.clear_cache()
|
||||
|
||||
def create_default_warehouses(self):
|
||||
@@ -191,7 +196,7 @@ class Company(NestedSet):
|
||||
def check_country_change(self):
|
||||
frappe.flags.country_change = False
|
||||
|
||||
if not self.get('__islocal') and \
|
||||
if not self.is_new() and \
|
||||
self.country != frappe.get_cached_value('Company', self.name, 'country'):
|
||||
frappe.flags.country_change = True
|
||||
|
||||
@@ -396,6 +401,13 @@ class Company(NestedSet):
|
||||
if not frappe.db.get_value('GL Entry', {'company': self.name}):
|
||||
frappe.db.sql("delete from `tabProcess Deferred Accounting` where company=%s", self.name)
|
||||
|
||||
def check_parent_changed(self):
|
||||
frappe.flags.parent_company_changed = False
|
||||
|
||||
if not self.is_new() and \
|
||||
self.parent_company != frappe.db.get_value("Company", self.name, "parent_company"):
|
||||
frappe.flags.parent_company_changed = True
|
||||
|
||||
def get_name_with_abbr(name, company):
|
||||
company_abbr = frappe.get_cached_value('Company', company, "abbr")
|
||||
parts = name.split(" - ")
|
||||
@@ -413,7 +425,7 @@ def install_country_fixtures(company, country):
|
||||
frappe.get_attr(module_name)(company, False)
|
||||
except Exception as e:
|
||||
frappe.log_error()
|
||||
frappe.throw(_("Failed to setup defaults for country {0}. Please contact support@erpnext.com").format(frappe.bold(country)))
|
||||
frappe.throw(_("Failed to setup defaults for country {0}. Please contact support.").format(frappe.bold(country)))
|
||||
|
||||
|
||||
def update_company_current_month_sales(company):
|
||||
|
||||
@@ -93,6 +93,61 @@ class TestCompany(unittest.TestCase):
|
||||
frappe.db.sql(""" delete from `tabMode of Payment Account`
|
||||
where company =%s """, (company))
|
||||
|
||||
def test_basic_tree(self, records=None):
|
||||
min_lft = 1
|
||||
max_rgt = frappe.db.sql("select max(rgt) from `tabCompany`")[0][0]
|
||||
|
||||
if not records:
|
||||
records = test_records[2:]
|
||||
|
||||
for company in records:
|
||||
lft, rgt, parent_company = frappe.db.get_value("Company", company["company_name"],
|
||||
["lft", "rgt", "parent_company"])
|
||||
|
||||
if parent_company:
|
||||
parent_lft, parent_rgt = frappe.db.get_value("Company", parent_company,
|
||||
["lft", "rgt"])
|
||||
else:
|
||||
# root
|
||||
parent_lft = min_lft - 1
|
||||
parent_rgt = max_rgt + 1
|
||||
|
||||
self.assertTrue(lft)
|
||||
self.assertTrue(rgt)
|
||||
self.assertTrue(lft < rgt)
|
||||
self.assertTrue(parent_lft < parent_rgt)
|
||||
self.assertTrue(lft > parent_lft)
|
||||
self.assertTrue(rgt < parent_rgt)
|
||||
self.assertTrue(lft >= min_lft)
|
||||
self.assertTrue(rgt <= max_rgt)
|
||||
|
||||
def get_no_of_children(self, company):
|
||||
def get_no_of_children(companies, no_of_children):
|
||||
children = []
|
||||
for company in companies:
|
||||
children += frappe.db.sql_list("""select name from `tabCompany`
|
||||
where ifnull(parent_company, '')=%s""", company or '')
|
||||
|
||||
if len(children):
|
||||
return get_no_of_children(children, no_of_children + len(children))
|
||||
else:
|
||||
return no_of_children
|
||||
|
||||
return get_no_of_children([company], 0)
|
||||
|
||||
def test_change_parent_company(self):
|
||||
child_company = frappe.get_doc("Company", "_Test Company 5")
|
||||
|
||||
# changing parent of company
|
||||
child_company.parent_company = "_Test Company 3"
|
||||
child_company.save()
|
||||
self.test_basic_tree()
|
||||
|
||||
# move it back
|
||||
child_company.parent_company = "_Test Company 4"
|
||||
child_company.save()
|
||||
self.test_basic_tree()
|
||||
|
||||
def create_company_communication(doctype, docname):
|
||||
comm = frappe.get_doc({
|
||||
"doctype": "Communication",
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"abbr": "_TC3",
|
||||
"company_name": "_Test Company 3",
|
||||
"is_group": 1,
|
||||
"country": "India",
|
||||
"country": "Pakistan",
|
||||
"default_currency": "INR",
|
||||
"doctype": "Company",
|
||||
"domain": "Manufacturing",
|
||||
@@ -49,7 +49,7 @@
|
||||
"company_name": "_Test Company 4",
|
||||
"parent_company": "_Test Company 3",
|
||||
"is_group": 1,
|
||||
"country": "India",
|
||||
"country": "Pakistan",
|
||||
"default_currency": "INR",
|
||||
"doctype": "Company",
|
||||
"domain": "Manufacturing",
|
||||
@@ -61,7 +61,7 @@
|
||||
"abbr": "_TC5",
|
||||
"company_name": "_Test Company 5",
|
||||
"parent_company": "_Test Company 4",
|
||||
"country": "India",
|
||||
"country": "Pakistan",
|
||||
"default_currency": "INR",
|
||||
"doctype": "Company",
|
||||
"domain": "Manufacturing",
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
QUnit.module('setup');
|
||||
|
||||
QUnit.test("Test: Company [SetUp]", function (assert) {
|
||||
assert.expect(2);
|
||||
let done = assert.async();
|
||||
|
||||
frappe.run_serially([
|
||||
// test company creation
|
||||
() => frappe.set_route("List", "Company", "List"),
|
||||
() => frappe.new_doc("Company"),
|
||||
() => frappe.timeout(1),
|
||||
() => cur_frm.set_value("company_name", "Test Company"),
|
||||
() => cur_frm.set_value("abbr", "TC"),
|
||||
() => cur_frm.set_value("domain", "Services"),
|
||||
() => cur_frm.set_value("default_currency", "INR"),
|
||||
// save form
|
||||
() => cur_frm.save(),
|
||||
() => frappe.timeout(1),
|
||||
() => assert.equal("Debtors - TC", cur_frm.doc.default_receivable_account,
|
||||
'chart of acounts created'),
|
||||
() => assert.equal("Main - TC", cur_frm.doc.cost_center,
|
||||
'chart of cost centers created'),
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
@@ -1,19 +0,0 @@
|
||||
QUnit.test("Test: Company", function (assert) {
|
||||
assert.expect(0);
|
||||
|
||||
let done = assert.async();
|
||||
|
||||
frappe.run_serially([
|
||||
// Added company for Work Order testing
|
||||
() => frappe.set_route("List", "Company"),
|
||||
() => frappe.new_doc("Company"),
|
||||
() => frappe.timeout(1),
|
||||
() => cur_frm.set_value("company_name", "For Testing"),
|
||||
() => cur_frm.set_value("abbr", "RB"),
|
||||
() => cur_frm.set_value("default_currency", "INR"),
|
||||
() => cur_frm.save(),
|
||||
() => frappe.timeout(1),
|
||||
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
@@ -62,8 +62,13 @@ def patched_requests_get(*args, **kwargs):
|
||||
if kwargs['params'].get('date') and kwargs['params'].get('from') and kwargs['params'].get('to'):
|
||||
if test_exchange_values.get(kwargs['params']['date']):
|
||||
return PatchResponse({'result': test_exchange_values[kwargs['params']['date']]}, 200)
|
||||
elif args[0].startswith("https://frankfurter.app") and kwargs.get('params'):
|
||||
if kwargs['params'].get('base') and kwargs['params'].get('symbols'):
|
||||
date = args[0].replace("https://frankfurter.app/", "")
|
||||
if test_exchange_values.get(date):
|
||||
return PatchResponse({'rates': {kwargs['params'].get('symbols'): test_exchange_values.get(date)}}, 200)
|
||||
|
||||
return PatchResponse({'result': None}, 404)
|
||||
return PatchResponse({'rates': None}, 404)
|
||||
|
||||
@mock.patch('requests.get', side_effect=patched_requests_get)
|
||||
class TestCurrencyExchange(unittest.TestCase):
|
||||
@@ -102,6 +107,41 @@ class TestCurrencyExchange(unittest.TestCase):
|
||||
self.assertFalse(exchange_rate == 60)
|
||||
self.assertEqual(flt(exchange_rate, 3), 65.1)
|
||||
|
||||
def test_exchange_rate_via_exchangerate_host(self, mock_get):
|
||||
save_new_records(test_records)
|
||||
|
||||
# Update Currency Exchange Rate
|
||||
settings = frappe.get_single("Currency Exchange Settings")
|
||||
settings.service_provider = 'exchangerate.host'
|
||||
settings.save()
|
||||
|
||||
# Update exchange
|
||||
frappe.db.set_value("Accounts Settings", None, "allow_stale", 1)
|
||||
|
||||
# Start with allow_stale is True
|
||||
exchange_rate = get_exchange_rate("USD", "INR", "2016-01-01", "for_buying")
|
||||
self.assertEqual(flt(exchange_rate, 3), 60.0)
|
||||
|
||||
exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15", "for_buying")
|
||||
self.assertEqual(exchange_rate, 65.1)
|
||||
|
||||
exchange_rate = get_exchange_rate("USD", "INR", "2016-01-30", "for_selling")
|
||||
self.assertEqual(exchange_rate, 62.9)
|
||||
|
||||
# Exchange rate as on 15th Dec, 2015
|
||||
self.clear_cache()
|
||||
exchange_rate = get_exchange_rate("USD", "INR", "2015-12-15", "for_selling")
|
||||
self.assertFalse(exchange_rate == 60)
|
||||
self.assertEqual(flt(exchange_rate, 3), 66.999)
|
||||
|
||||
exchange_rate = get_exchange_rate("USD", "INR", "2016-01-20", "for_buying")
|
||||
self.assertFalse(exchange_rate == 60)
|
||||
self.assertEqual(flt(exchange_rate, 3), 65.1)
|
||||
|
||||
settings = frappe.get_single("Currency Exchange Settings")
|
||||
settings.service_provider = 'frankfurter.app'
|
||||
settings.save()
|
||||
|
||||
def test_exchange_rate_strict(self, mock_get):
|
||||
# strict currency settings
|
||||
frappe.db.set_value("Accounts Settings", None, "allow_stale", 0)
|
||||
|
||||
67
erpnext/setup/form_tour/company/company.json
Normal file
67
erpnext/setup/form_tour/company/company.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"creation": "2021-11-24 10:17:18.534917",
|
||||
"docstatus": 0,
|
||||
"doctype": "Form Tour",
|
||||
"first_document": 1,
|
||||
"idx": 0,
|
||||
"include_name_field": 0,
|
||||
"is_standard": 1,
|
||||
"modified": "2021-11-24 15:38:21.026582",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Company",
|
||||
"owner": "Administrator",
|
||||
"reference_doctype": "Company",
|
||||
"save_on_complete": 0,
|
||||
"steps": [
|
||||
{
|
||||
"description": "This is the default currency for this company.",
|
||||
"field": "",
|
||||
"fieldname": "default_currency",
|
||||
"fieldtype": "Link",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Default Currency",
|
||||
"parent_field": "",
|
||||
"position": "Right",
|
||||
"title": "Default Currency"
|
||||
},
|
||||
{
|
||||
"description": "Here, you can add multiple addresses of the company",
|
||||
"field": "",
|
||||
"fieldname": "company_info",
|
||||
"fieldtype": "Section Break",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Address & Contact",
|
||||
"parent_field": "",
|
||||
"position": "Top",
|
||||
"title": "Address & Contact"
|
||||
},
|
||||
{
|
||||
"description": "Here, you can set default Accounts, which will ease the creation of accounting entries.",
|
||||
"field": "",
|
||||
"fieldname": "default_settings",
|
||||
"fieldtype": "Section Break",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Accounts Settings",
|
||||
"parent_field": "",
|
||||
"position": "Top",
|
||||
"title": "Accounts Settings"
|
||||
},
|
||||
{
|
||||
"description": "This setting is recommended if you wish to track the real-time stock balance in your books of account. This will allow the creation of a General Ledger entry for every stock transaction.",
|
||||
"field": "",
|
||||
"fieldname": "enable_perpetual_inventory",
|
||||
"fieldtype": "Check",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Enable Perpetual Inventory",
|
||||
"parent_field": "",
|
||||
"position": "Right",
|
||||
"title": "Enable Perpetual Inventory"
|
||||
}
|
||||
],
|
||||
"title": "Company"
|
||||
}
|
||||
@@ -60,6 +60,22 @@ def set_single_defaults():
|
||||
|
||||
frappe.db.set_default("date_format", "dd-mm-yyyy")
|
||||
|
||||
setup_currency_exchange()
|
||||
|
||||
def setup_currency_exchange():
|
||||
ces = frappe.get_single('Currency Exchange Settings')
|
||||
try:
|
||||
ces.set('result_key', [])
|
||||
ces.set('req_params', [])
|
||||
|
||||
ces.api_endpoint = "https://frankfurter.app/{transaction_date}"
|
||||
ces.append('result_key', {'key': 'rates'})
|
||||
ces.append('result_key', {'key': '{to_currency}'})
|
||||
ces.append('req_params', {'key': 'base', 'value': '{from_currency}'})
|
||||
ces.append('req_params', {'key': 'symbols', 'value': '{to_currency}'})
|
||||
ces.save()
|
||||
except frappe.ValidationError:
|
||||
pass
|
||||
|
||||
def create_compact_item_print_custom_field():
|
||||
create_custom_field('Print Settings', {
|
||||
|
||||
62
erpnext/setup/module_onboarding/home/home.json
Normal file
62
erpnext/setup/module_onboarding/home/home.json
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"allow_roles": [
|
||||
{
|
||||
"role": "Accounts Manager"
|
||||
},
|
||||
{
|
||||
"role": "Stock Manager"
|
||||
},
|
||||
{
|
||||
"role": "Sales Manager"
|
||||
},
|
||||
{
|
||||
"role": "Purchase Manager"
|
||||
},
|
||||
{
|
||||
"role": "Manufacturing Manager"
|
||||
},
|
||||
{
|
||||
"role": "Item Manager"
|
||||
}
|
||||
],
|
||||
"creation": "2021-11-22 12:19:15.888642",
|
||||
"docstatus": 0,
|
||||
"doctype": "Module Onboarding",
|
||||
"documentation_url": "https://docs.erpnext.com/docs/v13/user/manual/en/setting-up/company-setup",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"modified": "2021-12-15 14:23:52.460913",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Home",
|
||||
"owner": "Administrator",
|
||||
"steps": [
|
||||
{
|
||||
"step": "Company Set Up"
|
||||
},
|
||||
{
|
||||
"step": "Navigation Help"
|
||||
},
|
||||
{
|
||||
"step": "Data import"
|
||||
},
|
||||
{
|
||||
"step": "Create an Item"
|
||||
},
|
||||
{
|
||||
"step": "Create a Customer"
|
||||
},
|
||||
{
|
||||
"step": "Create a Supplier"
|
||||
},
|
||||
{
|
||||
"step": "Create a Quotation"
|
||||
},
|
||||
{
|
||||
"step": "Letterhead"
|
||||
}
|
||||
],
|
||||
"subtitle": "Company, Item, Customer, Supplier, Navigation Help, Data Import, Letter Head, Quotation",
|
||||
"success_message": "Masters are all set up!",
|
||||
"title": "Let's Set Up Some Masters"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"action_label": "Let's review your Company",
|
||||
"creation": "2021-11-22 11:55:48.931427",
|
||||
"description": "# Set Up a Company\n\nA company is a legal entity for which you will set up your books of account and create accounting transactions. In ERPNext, you can create multiple companies, and establish relationships (group/subsidiary) among them.\n\nWithin the company master, you can capture various default accounts for that Company and set crucial settings related to the accounting methodology followed for a company.\n",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-12-15 14:22:18.317423",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Company Set Up",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Company",
|
||||
"show_form_tour": 1,
|
||||
"show_full_form": 1,
|
||||
"title": "Set Up a Company",
|
||||
"validate_action": 1
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"action_label": "Let\u2019s create your first Customer",
|
||||
"creation": "2020-05-14 17:46:41.831517",
|
||||
"description": "# Create a Customer\n\nThe Customer master is at the heart of your sales transactions. Customers are linked in Quotations, Sales Orders, Invoices, and Payments. Customers can be either numbered or identified by name (you would typically do this based on the number of customers you have).\n\nThrough Customer\u2019s master, you can effectively track essentials like:\n - Customer\u2019s multiple address and contacts\n - Account Receivables\n - Credit Limit and Credit Period\n",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-12-15 14:20:31.197564",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create a Customer",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Customer",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Manage Customers",
|
||||
"validate_action": 1
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"action_label": "Let\u2019s create your first Quotation",
|
||||
"creation": "2020-06-01 13:34:58.958641",
|
||||
"description": "# Create a Quotation\n\nLet\u2019s get started with business transactions by creating your first Quotation. You can create a Quotation for an existing customer or a prospect. It will be an approved document, with items you sell and the proposed price + taxes applied. After completing the instructions, you will get a Quotation in a ready to share print format.",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-12-15 14:21:31.675330",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create a Quotation",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Quotation",
|
||||
"show_form_tour": 1,
|
||||
"show_full_form": 1,
|
||||
"title": "Create your first Quotation",
|
||||
"validate_action": 1
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"action_label": "Let\u2019s create your first Supplier",
|
||||
"creation": "2020-05-14 22:09:10.043554",
|
||||
"description": "# Create a Supplier\n\nAlso known as Vendor, is a master at the center of your purchase transactions. Suppliers are linked in Request for Quotation, Purchase Orders, Receipts, and Payments. Suppliers can be either numbered or identified by name.\n\nThrough Supplier\u2019s master, you can effectively track essentials like:\n - Supplier\u2019s multiple address and contacts\n - Account Receivables\n - Credit Limit and Credit Period\n",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-12-15 14:21:23.518301",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create a Supplier",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Supplier",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Manage Suppliers",
|
||||
"validate_action": 1
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"action_label": "Create a new Item",
|
||||
"creation": "2021-05-17 13:47:18.515052",
|
||||
"description": "# Create an Item\n\nItem is a product, of a or service offered by your company, or something you buy as a part of your supplies or raw materials.\n\nItems are integral to everything you do in ERPNext - from billing, purchasing to managing inventory. Everything you buy or sell, whether it is a physical product or a service is an Item. Items can be stock, non-stock, variants, serialized, batched, assets etc.\n",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"form_tour": "Item General",
|
||||
"idx": 0,
|
||||
"intro_video_url": "",
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-12-15 14:19:56.297772",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create an Item",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Item",
|
||||
"show_form_tour": 1,
|
||||
"show_full_form": 1,
|
||||
"title": "Manage Items",
|
||||
"validate_action": 1
|
||||
}
|
||||
21
erpnext/setup/onboarding_step/data_import/data_import.json
Normal file
21
erpnext/setup/onboarding_step/data_import/data_import.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Watch Video",
|
||||
"action_label": "Learn more about data migration",
|
||||
"creation": "2021-05-19 05:29:16.809610",
|
||||
"description": "# Import Data from Spreadsheet\n\nIn ERPNext, you can easily migrate your historical data using spreadsheets. You can use it for migrating not just masters (like Customer, Supplier, Items), but also for transactions like (outstanding invoices, opening stock and accounting entries, etc). If you are migrating from [Tally](https://tallysolutions.com/) or [Quickbooks](https://quickbooks.intuit.com/in/), we got special migration tools for you.",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-12-15 13:10:57.346422",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Data import",
|
||||
"owner": "Administrator",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Import Data from Spreadsheet",
|
||||
"validate_action": 1,
|
||||
"video_url": "https://youtu.be/DQyqeurPI64"
|
||||
}
|
||||
21
erpnext/setup/onboarding_step/letterhead/letterhead.json
Normal file
21
erpnext/setup/onboarding_step/letterhead/letterhead.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"action_label": "Let\u2019s setup your first Letter Head",
|
||||
"creation": "2021-11-22 12:36:34.583783",
|
||||
"description": "# Create a Letter Head\n\nA Letter Head contains your organization's name, logo, address, etc which appears at the header and footer portion in documents. You can learn more about Setting up Letter Head in ERPNext here.\n",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-12-15 14:21:39.037742",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Letterhead",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Letter Head",
|
||||
"show_form_tour": 1,
|
||||
"show_full_form": 1,
|
||||
"title": "Setup Your Letterhead",
|
||||
"validate_action": 1
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Watch Video",
|
||||
"action_label": "Learn about Navigation options",
|
||||
"creation": "2021-11-22 12:09:52.233872",
|
||||
"description": "# Navigation in ERPNext\n\nEase of navigating and browsing around the ERPNext is one of our core strengths. In the following video, you will learn how to reach a specific feature in ERPNext via module page or awesome bar\u2019s shortcut.\n",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-12-15 14:20:55.441678",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Navigation Help",
|
||||
"owner": "Administrator",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "How to Navigate in ERPNext",
|
||||
"validate_action": 1,
|
||||
"video_url": "https://youtu.be/j60xyNFqX_A"
|
||||
}
|
||||
@@ -1178,11 +1178,13 @@
|
||||
{
|
||||
"title": "Reverse Charge In-State",
|
||||
"is_inter_state": 0,
|
||||
"is_reverse_charge": 1,
|
||||
"gst_state": ""
|
||||
},
|
||||
{
|
||||
"title": "Reverse Charge Out-State",
|
||||
"is_inter_state": 1,
|
||||
"is_reverse_charge": 1,
|
||||
"gst_state": ""
|
||||
},
|
||||
{
|
||||
|
||||
@@ -68,6 +68,8 @@ def set_default_settings(args):
|
||||
|
||||
hr_settings.send_interview_feedback_reminder = 1
|
||||
hr_settings.feedback_reminder_notification_template = _("Interview Feedback Reminder")
|
||||
|
||||
hr_settings.exit_questionnaire_notification_template = _("Exit Questionnaire Notification")
|
||||
hr_settings.save()
|
||||
|
||||
def set_no_copy_fields_in_variant_settings():
|
||||
|
||||
@@ -33,7 +33,6 @@ def install(country=None):
|
||||
{ 'doctype': 'Domain', 'domain': 'Services'},
|
||||
{ 'doctype': 'Domain', 'domain': 'Education'},
|
||||
{ 'doctype': 'Domain', 'domain': 'Healthcare'},
|
||||
{ 'doctype': 'Domain', 'domain': 'Agriculture'},
|
||||
{ 'doctype': 'Domain', 'domain': 'Non Profit'},
|
||||
|
||||
# ensure at least an empty Address Template exists for this Country
|
||||
@@ -278,6 +277,11 @@ def install(country=None):
|
||||
records += [{'doctype': 'Email Template', 'name': _('Interview Feedback Reminder'), 'response': response,
|
||||
'subject': _('Interview Feedback Reminder'), 'owner': frappe.session.user}]
|
||||
|
||||
response = frappe.read_file(os.path.join(base_path, 'exit_interview/exit_questionnaire_notification_template.html'))
|
||||
|
||||
records += [{'doctype': 'Email Template', 'name': _('Exit Questionnaire Notification'), 'response': response,
|
||||
'subject': _('Exit Questionnaire Notification'), 'owner': frappe.session.user}]
|
||||
|
||||
base_path = frappe.get_app_path("erpnext", "stock", "doctype")
|
||||
response = frappe.read_file(os.path.join(base_path, "delivery_trip/dispatch_notification_template.html"))
|
||||
|
||||
@@ -303,7 +307,6 @@ def set_more_defaults():
|
||||
|
||||
def update_selling_defaults():
|
||||
selling_settings = frappe.get_doc("Selling Settings")
|
||||
selling_settings.set_default_customer_group_and_territory()
|
||||
selling_settings.cust_master_name = "Customer Name"
|
||||
selling_settings.so_required = "No"
|
||||
selling_settings.dn_required = "No"
|
||||
@@ -350,7 +353,8 @@ def add_uom_data():
|
||||
"doctype": "UOM",
|
||||
"uom_name": _(d.get("uom_name")),
|
||||
"name": _(d.get("uom_name")),
|
||||
"must_be_whole_number": d.get("must_be_whole_number")
|
||||
"must_be_whole_number": d.get("must_be_whole_number"),
|
||||
"enabled": 1,
|
||||
}).db_insert()
|
||||
|
||||
# bootstrap uom conversion factors
|
||||
|
||||
@@ -53,6 +53,7 @@ def before_tests():
|
||||
|
||||
frappe.db.set_value("Stock Settings", None, "auto_insert_price_list_rate_if_missing", 0)
|
||||
enable_all_roles_and_domains()
|
||||
set_defaults_for_tests()
|
||||
|
||||
frappe.db.commit()
|
||||
|
||||
@@ -99,15 +100,21 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No
|
||||
|
||||
if not value:
|
||||
import requests
|
||||
api_url = "https://api.exchangerate.host/convert"
|
||||
response = requests.get(api_url, params={
|
||||
"date": transaction_date,
|
||||
"from": from_currency,
|
||||
"to": to_currency
|
||||
})
|
||||
settings = frappe.get_cached_doc('Currency Exchange Settings')
|
||||
req_params = {
|
||||
"transaction_date": transaction_date,
|
||||
"from_currency": from_currency,
|
||||
"to_currency": to_currency
|
||||
}
|
||||
params = {}
|
||||
for row in settings.req_params:
|
||||
params[row.key] = format_ces_api(row.value, req_params)
|
||||
response = requests.get(format_ces_api(settings.api_endpoint, req_params), params=params)
|
||||
# expire in 6 hours
|
||||
response.raise_for_status()
|
||||
value = response.json()["result"]
|
||||
value = response.json()
|
||||
for res_key in settings.result_key:
|
||||
value = value[format_ces_api(str(res_key.key), req_params)]
|
||||
cache.setex(name=key, time=21600, value=flt(value))
|
||||
return flt(value)
|
||||
except Exception:
|
||||
@@ -115,6 +122,13 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No
|
||||
frappe.msgprint(_("Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually").format(from_currency, to_currency, transaction_date))
|
||||
return 0.0
|
||||
|
||||
def format_ces_api(data, param):
|
||||
return data.format(
|
||||
transaction_date=param.get("transaction_date"),
|
||||
to_currency=param.get("to_currency"),
|
||||
from_currency=param.get("from_currency")
|
||||
)
|
||||
|
||||
def enable_all_roles_and_domains():
|
||||
""" enable all roles and domain for testing """
|
||||
# add all roles to users
|
||||
@@ -127,6 +141,14 @@ def enable_all_roles_and_domains():
|
||||
[d.name for d in domains])
|
||||
add_all_roles_to('Administrator')
|
||||
|
||||
def set_defaults_for_tests():
|
||||
from frappe.utils.nestedset import get_root_of
|
||||
|
||||
selling_settings = frappe.get_single("Selling Settings")
|
||||
selling_settings.customer_group = get_root_of("Customer Group")
|
||||
selling_settings.territory = get_root_of("Territory")
|
||||
selling_settings.save()
|
||||
|
||||
|
||||
def insert_record(records):
|
||||
for r in records:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"idx": 0,
|
||||
"label": "ERPNext Settings",
|
||||
"links": [],
|
||||
"modified": "2021-10-26 21:32:55.323591",
|
||||
"modified": "2021-11-05 21:32:55.323591",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "ERPNext Settings",
|
||||
@@ -123,6 +123,13 @@
|
||||
"label": "Products Settings",
|
||||
"link_to": "Products Settings",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"doc_view": "",
|
||||
"icon": "crm",
|
||||
"label": "CRM Settings",
|
||||
"link_to": "CRM Settings",
|
||||
"type": "DocType"
|
||||
}
|
||||
],
|
||||
"title": "ERPNext Settings"
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
{
|
||||
"charts": [],
|
||||
"content": "[{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Customer\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Supplier\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Leaderboard\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Human Resources\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"CRM\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Data Import and Settings\",\"col\":4}}]",
|
||||
"content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Home\",\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Customer\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Supplier\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Leaderboard\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Human Resources\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"CRM\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Data Import and Settings\",\"col\":4}}]",
|
||||
"creation": "2020-01-23 13:46:38.833076",
|
||||
"developer_mode_only": 0,
|
||||
"disable_user_customization": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Workspace",
|
||||
"extends_another_page": 0,
|
||||
"for_user": "",
|
||||
"hide_custom": 0,
|
||||
"icon": "getting-started",
|
||||
"idx": 0,
|
||||
"is_default": 0,
|
||||
"is_standard": 0,
|
||||
"label": "Home",
|
||||
"links": [
|
||||
{
|
||||
@@ -271,12 +276,14 @@
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2021-08-10 15:33:20.704741",
|
||||
"modified": "2021-11-22 12:50:15.771366",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Home",
|
||||
"owner": "Administrator",
|
||||
"parent_page": "",
|
||||
"pin_to_bottom": 0,
|
||||
"pin_to_top": 0,
|
||||
"public": 1,
|
||||
"restrict_to_domain": "",
|
||||
"roles": [],
|
||||
@@ -309,4 +316,4 @@
|
||||
}
|
||||
],
|
||||
"title": "Home"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user