Merge branch 'develop' into e-commerce-refactor-develop

This commit is contained in:
Marica
2022-01-12 02:52:03 +05:30
committed by GitHub
675 changed files with 13321 additions and 20904 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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()
]);
});

View File

@@ -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()
]);
});

View File

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

View 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"
}

View File

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

View 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"
}

View File

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

View File

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

View File

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

View File

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

View File

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

View 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"
}

View 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
}

View File

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

View File

@@ -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": ""
},
{

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 &amp; 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"
}
}