Browse Source

feat: multi-currency in Opportunity (#26590)

* feat: multi-currency

* refactor: lead form

* fix: test case for opportunity item

* fix: removing local changes

* fix: test cases

* fix: test cases

* fix: review changes

* fix: reverting lead.json chnages

* fix: toggle display for currency fields

* review changes

* fix: test case

* fix: linter issues

* fix: unused import

* feat: grand total in opportunity

* fix: patch

* fix: sort imports

* fix: reload opportunity item doctype

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
develop
Anupam Kumar 3 years ago
committed by GitHub
parent
commit
b0d970001a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 90
      erpnext/crm/doctype/opportunity/opportunity.js
  2. 65
      erpnext/crm/doctype/opportunity/opportunity.json
  3. 29
      erpnext/crm/doctype/opportunity/opportunity.py
  4. 6
      erpnext/crm/doctype/opportunity/test_opportunity.py
  5. 610
      erpnext/crm/doctype/opportunity_item/opportunity_item.json
  6. 1
      erpnext/patches.txt
  7. 36
      erpnext/patches/v14_0/update_opportunity_currency_fields.py

90
erpnext/crm/doctype/opportunity/opportunity.js

@ -132,10 +132,43 @@ frappe.ui.form.on("Opportunity", {
} }
}, },
currency: function(frm) {
let company_currency = erpnext.get_currency(frm.doc.company);
if (company_currency != frm.doc.company) {
frappe.call({
method: "erpnext.setup.utils.get_exchange_rate",
args: {
from_currency: frm.doc.currency,
to_currency: company_currency
},
callback: function(r) {
if (r.message) {
frm.set_value('conversion_rate', flt(r.message));
frm.set_df_property('conversion_rate', 'description', '1 ' + frm.doc.currency
+ ' = [?] ' + company_currency);
}
}
});
} else {
frm.set_value('conversion_rate', 1.0);
frm.set_df_property('conversion_rate', 'hidden', 1);
frm.set_df_property('conversion_rate', 'description', '');
}
frm.trigger('opportunity_amount');
frm.trigger('set_dynamic_field_label');
},
opportunity_amount: function(frm) {
frm.set_value('base_opportunity_amount', flt(frm.doc.opportunity_amount) * flt(frm.doc.conversion_rate));
},
set_dynamic_field_label: function(frm){ set_dynamic_field_label: function(frm){
if (frm.doc.opportunity_from) { if (frm.doc.opportunity_from) {
frm.set_df_property("party_name", "label", frm.doc.opportunity_from); frm.set_df_property("party_name", "label", frm.doc.opportunity_from);
} }
frm.trigger('change_grid_labels');
frm.trigger('change_form_labels');
}, },
make_supplier_quotation: function(frm) { make_supplier_quotation: function(frm) {
@ -152,6 +185,62 @@ frappe.ui.form.on("Opportunity", {
}) })
}, },
change_form_labels: function(frm) {
let company_currency = erpnext.get_currency(frm.doc.company);
frm.set_currency_labels(["base_opportunity_amount", "base_total", "base_grand_total"], company_currency);
frm.set_currency_labels(["opportunity_amount", "total", "grand_total"], frm.doc.currency);
// toggle fields
frm.toggle_display(["conversion_rate", "base_opportunity_amount", "base_total", "base_grand_total"],
frm.doc.currency != company_currency);
},
change_grid_labels: function(frm) {
let company_currency = erpnext.get_currency(frm.doc.company);
frm.set_currency_labels(["base_rate", "base_amount"], company_currency, "items");
frm.set_currency_labels(["rate", "amount"], frm.doc.currency, "items");
let item_grid = frm.fields_dict.items.grid;
$.each(["base_rate", "base_amount"], function(i, fname) {
if(frappe.meta.get_docfield(item_grid.doctype, fname))
item_grid.set_column_disp(fname, frm.doc.currency != company_currency);
});
frm.refresh_fields();
},
calculate_total: function(frm) {
let total = 0, base_total = 0, grand_total = 0, base_grand_total = 0;
frm.doc.items.forEach(item => {
total += item.amount;
base_total += item.base_amount;
})
base_grand_total = base_total + frm.doc.base_opportunity_amount;
grand_total = total + frm.doc.opportunity_amount;
frm.set_value({
'total': flt(total),
'base_total': flt(base_total),
'grand_total': flt(grand_total),
'base_grand_total': flt(base_grand_total)
});
}
});
frappe.ui.form.on("Opportunity Item", {
calculate: function(frm, cdt, cdn) {
let row = frappe.get_doc(cdt, cdn);
frappe.model.set_value(cdt, cdn, "amount", flt(row.qty) * flt(row.rate));
frappe.model.set_value(cdt, cdn, "base_rate", flt(frm.doc.conversion_rate) * flt(row.rate));
frappe.model.set_value(cdt, cdn, "base_amount", flt(frm.doc.conversion_rate) * flt(row.amount));
frm.trigger("calculate_total");
},
qty: function(frm, cdt, cdn) {
frm.trigger("calculate", cdt, cdn);
},
rate: function(frm, cdt, cdn) {
frm.trigger("calculate", cdt, cdn);
}
}) })
// TODO commonify this code // TODO commonify this code
@ -169,6 +258,7 @@ erpnext.crm.Opportunity = class Opportunity extends frappe.ui.form.Controller {
} }
this.setup_queries(); this.setup_queries();
this.frm.trigger('currency');
} }
setup_queries() { setup_queries() {

65
erpnext/crm/doctype/opportunity/opportunity.json

@ -33,12 +33,20 @@
"to_discuss", "to_discuss",
"section_break_14", "section_break_14",
"currency", "currency",
"opportunity_amount", "conversion_rate",
"base_opportunity_amount",
"with_items", "with_items",
"column_break_17", "column_break_17",
"probability", "probability",
"opportunity_amount",
"items_section", "items_section",
"items", "items",
"section_break_32",
"base_total",
"base_grand_total",
"column_break_33",
"total",
"grand_total",
"contact_info", "contact_info",
"customer_address", "customer_address",
"address_display", "address_display",
@ -425,12 +433,65 @@
"fieldtype": "Link", "fieldtype": "Link",
"label": "Print Language", "label": "Print Language",
"options": "Language" "options": "Language"
},
{
"fieldname": "base_opportunity_amount",
"fieldtype": "Currency",
"label": "Opportunity Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
},
{
"depends_on": "with_items",
"fieldname": "section_break_32",
"fieldtype": "Section Break",
"hide_border": 1
},
{
"fieldname": "base_total",
"fieldtype": "Currency",
"label": "Total (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "total",
"fieldtype": "Currency",
"label": "Total",
"options": "currency",
"read_only": 1
},
{
"fieldname": "conversion_rate",
"fieldtype": "Float",
"label": "Exchange Rate"
},
{
"fieldname": "column_break_33",
"fieldtype": "Column Break"
},
{
"fieldname": "base_grand_total",
"fieldtype": "Currency",
"label": "Grand Total (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "grand_total",
"fieldtype": "Currency",
"label": "Grand Total",
"options": "currency",
"read_only": 1
} }
], ],
"icon": "fa fa-info-sign", "icon": "fa fa-info-sign",
"idx": 195, "idx": 195,
"links": [], "links": [],
"modified": "2021-08-25 10:28:24.923543", "modified": "2021-09-06 10:02:18.609136",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "CRM", "module": "CRM",
"name": "Opportunity", "name": "Opportunity",

29
erpnext/crm/doctype/opportunity/opportunity.py

@ -9,9 +9,8 @@ import frappe
from frappe import _ from frappe import _
from frappe.email.inbox import link_communication_to_document from frappe.email.inbox import link_communication_to_document
from frappe.model.mapper import get_mapped_doc from frappe.model.mapper import get_mapped_doc
from frappe.utils import cint, cstr, get_fullname from frappe.utils import cint, cstr, flt, get_fullname
from erpnext.accounts.party import get_party_account_currency
from erpnext.setup.utils import get_exchange_rate from erpnext.setup.utils import get_exchange_rate
from erpnext.utilities.transaction_base import TransactionBase from erpnext.utilities.transaction_base import TransactionBase
@ -41,6 +40,23 @@ class Opportunity(TransactionBase):
if not self.with_items: if not self.with_items:
self.items = [] self.items = []
else:
self.calculate_totals()
def calculate_totals(self):
total = base_total = 0
for item in self.get('items'):
item.amount = flt(item.rate) * flt(item.qty)
item.base_rate = flt(self.conversion_rate * item.rate)
item.base_amount = flt(self.conversion_rate * item.amount)
total += item.amount
base_total += item.base_amount
self.total = flt(total)
self.base_total = flt(base_total)
self.grand_total = flt(self.total) + flt(self.opportunity_amount)
self.base_grand_total = flt(self.base_total) + flt(self.base_opportunity_amount)
def make_new_lead_if_required(self): def make_new_lead_if_required(self):
"""Set lead against new opportunity""" """Set lead against new opportunity"""
if (not self.get("party_name")) and self.contact_email: if (not self.get("party_name")) and self.contact_email:
@ -224,13 +240,6 @@ def make_quotation(source_name, target_doc=None):
company_currency = frappe.get_cached_value('Company', quotation.company, "default_currency") company_currency = frappe.get_cached_value('Company', quotation.company, "default_currency")
if quotation.quotation_to == 'Customer' and quotation.party_name:
party_account_currency = get_party_account_currency("Customer", quotation.party_name, quotation.company)
else:
party_account_currency = company_currency
quotation.currency = party_account_currency or company_currency
if company_currency == quotation.currency: if company_currency == quotation.currency:
exchange_rate = 1 exchange_rate = 1
else: else:
@ -254,7 +263,7 @@ def make_quotation(source_name, target_doc=None):
"doctype": "Quotation", "doctype": "Quotation",
"field_map": { "field_map": {
"opportunity_from": "quotation_to", "opportunity_from": "quotation_to",
"name": "enq_no", "name": "enq_no"
} }
}, },
"Opportunity Item": { "Opportunity Item": {

6
erpnext/crm/doctype/opportunity/test_opportunity.py

@ -63,6 +63,10 @@ class TestOpportunity(unittest.TestCase):
self.assertEqual(opp_doc.opportunity_from, "Customer") self.assertEqual(opp_doc.opportunity_from, "Customer")
self.assertEqual(opp_doc.party_name, customer.name) self.assertEqual(opp_doc.party_name, customer.name)
def test_opportunity_item(self):
opportunity_doc = make_opportunity(with_items=1, rate=1100, qty=2)
self.assertEqual(opportunity_doc.total, 2200)
def make_opportunity(**args): def make_opportunity(**args):
args = frappe._dict(args) args = frappe._dict(args)
@ -71,6 +75,7 @@ def make_opportunity(**args):
"company": args.company or "_Test Company", "company": args.company or "_Test Company",
"opportunity_from": args.opportunity_from or "Customer", "opportunity_from": args.opportunity_from or "Customer",
"opportunity_type": "Sales", "opportunity_type": "Sales",
"conversion_rate": 1.0,
"with_items": args.with_items or 0, "with_items": args.with_items or 0,
"transaction_date": today() "transaction_date": today()
}) })
@ -85,6 +90,7 @@ def make_opportunity(**args):
opp_doc.append('items', { opp_doc.append('items', {
"item_code": args.item_code or "_Test Item", "item_code": args.item_code or "_Test Item",
"qty": args.qty or 1, "qty": args.qty or 1,
"rate": args.rate or 1000,
"uom": "_Test UOM" "uom": "_Test UOM"
}) })

610
erpnext/crm/doctype/opportunity_item/opportunity_item.json

@ -1,469 +1,177 @@
{ {
"allow_copy": 0, "actions": [],
"allow_events_in_timeline": 0, "creation": "2013-02-22 01:27:51",
"allow_guest_to_view": 0, "doctype": "DocType",
"allow_import": 0, "editable_grid": 1,
"allow_rename": 0, "engine": "InnoDB",
"beta": 0, "field_order": [
"creation": "2013-02-22 01:27:51", "item_code",
"custom": 0, "item_name",
"docstatus": 0, "col_break1",
"doctype": "DocType", "uom",
"editable_grid": 1, "qty",
"engine": "InnoDB", "section_break_6",
"brand",
"item_group",
"description",
"column_break_8",
"image",
"image_view",
"quantity_and_rate_section",
"base_rate",
"base_amount",
"column_break_16",
"rate",
"amount"
],
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0, "fieldname": "item_code",
"allow_in_quick_entry": 0, "fieldtype": "Link",
"allow_on_submit": 0, "in_list_view": 1,
"bold": 0, "label": "Item Code",
"collapsible": 0, "oldfieldname": "item_code",
"columns": 0, "oldfieldtype": "Link",
"fieldname": "item_code", "options": "Item"
"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": "Item Code",
"length": 0,
"no_copy": 0,
"oldfieldname": "item_code",
"oldfieldtype": "Link",
"options": "Item",
"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, "fieldname": "col_break1",
"allow_in_quick_entry": 0, "fieldtype": "Column Break"
"allow_on_submit": 0, },
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "col_break1",
"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,
"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, "default": "1",
"allow_in_quick_entry": 0, "fieldname": "qty",
"allow_on_submit": 0, "fieldtype": "Float",
"bold": 0, "in_list_view": 1,
"collapsible": 0, "label": "Qty",
"columns": 0, "oldfieldname": "qty",
"fieldname": "qty", "oldfieldtype": "Currency"
"fieldtype": "Float", },
"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": "Qty",
"length": 0,
"no_copy": 0,
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"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, "fieldname": "item_group",
"allow_in_quick_entry": 0, "fieldtype": "Link",
"allow_on_submit": 0, "hidden": 1,
"bold": 0, "label": "Item Group",
"collapsible": 0, "oldfieldname": "item_group",
"columns": 0, "oldfieldtype": "Link",
"description": "", "options": "Item Group",
"fieldname": "item_group", "print_hide": 1
"fieldtype": "Link", },
"hidden": 1,
"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 Group",
"length": 0,
"no_copy": 0,
"oldfieldname": "item_group",
"oldfieldtype": "Link",
"options": "Item Group",
"permlevel": 0,
"print_hide": 1,
"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, "fieldname": "brand",
"allow_in_quick_entry": 0, "fieldtype": "Link",
"allow_on_submit": 0, "hidden": 1,
"bold": 0, "label": "Brand",
"collapsible": 0, "oldfieldname": "brand",
"columns": 0, "oldfieldtype": "Link",
"fieldname": "brand", "options": "Brand",
"fieldtype": "Link", "print_hide": 1
"hidden": 1, },
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Brand",
"length": 0,
"no_copy": 0,
"oldfieldname": "brand",
"oldfieldtype": "Link",
"options": "Brand",
"permlevel": 0,
"print_hide": 1,
"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, "collapsible": 1,
"allow_in_quick_entry": 0, "fieldname": "section_break_6",
"allow_on_submit": 0, "fieldtype": "Section Break",
"bold": 0, "label": "Description"
"collapsible": 0, },
"columns": 0,
"fieldname": "section_break_6",
"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,
"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, "fieldname": "uom",
"allow_in_quick_entry": 0, "fieldtype": "Link",
"allow_on_submit": 0, "label": "UOM",
"bold": 0, "oldfieldname": "uom",
"collapsible": 0, "oldfieldtype": "Link",
"columns": 0, "options": "UOM"
"fieldname": "uom", },
"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": "UOM",
"length": 0,
"no_copy": 0,
"oldfieldname": "uom",
"oldfieldtype": "Link",
"options": "UOM",
"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, "fieldname": "item_name",
"allow_in_quick_entry": 0, "fieldtype": "Data",
"allow_on_submit": 0, "in_global_search": 1,
"bold": 0, "label": "Item Name",
"collapsible": 0, "oldfieldname": "item_name",
"columns": 0, "oldfieldtype": "Data"
"fieldname": "item_name", },
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Item Name",
"length": 0,
"no_copy": 0,
"oldfieldname": "item_name",
"oldfieldtype": "Data",
"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, "fieldname": "description",
"allow_in_quick_entry": 0, "fieldtype": "Text Editor",
"allow_on_submit": 0, "label": "Description",
"bold": 0, "oldfieldname": "description",
"collapsible": 0, "oldfieldtype": "Text",
"columns": 0, "print_width": "300px",
"fieldname": "description",
"fieldtype": "Text Editor",
"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": "Description",
"length": 0,
"no_copy": 0,
"oldfieldname": "description",
"oldfieldtype": "Text",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "300px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "300px" "width": "300px"
}, },
{ {
"allow_bulk_edit": 0, "fieldname": "column_break_8",
"allow_in_quick_entry": 0, "fieldtype": "Column Break"
"allow_on_submit": 0, },
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_8",
"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, "fieldname": "image",
"allow_in_quick_entry": 0, "fieldtype": "Attach",
"allow_on_submit": 0, "hidden": 1,
"bold": 0, "label": "Image"
"collapsible": 0, },
"columns": 0,
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Image",
"length": 0,
"no_copy": 0,
"options": "",
"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, "fieldname": "image_view",
"allow_in_quick_entry": 0, "fieldtype": "Image",
"allow_on_submit": 0, "label": "Image View",
"bold": 0, "options": "image",
"collapsible": 0, "print_hide": 1
"columns": 0, },
"fieldname": "image_view",
"fieldtype": "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": "Image View",
"length": 0,
"no_copy": 0,
"options": "image",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"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, "fieldname": "rate",
"allow_in_quick_entry": 0, "fieldtype": "Currency",
"allow_on_submit": 0, "in_list_view": 1,
"bold": 0, "label": "Rate",
"collapsible": 0, "options": "currency",
"columns": 0, "reqd": 1
"fieldname": "basic_rate", },
"fieldtype": "Currency", {
"hidden": 1, "fieldname": "quantity_and_rate_section",
"ignore_user_permissions": 0, "fieldtype": "Section Break",
"ignore_xss_filter": 0, "label": "Quantity and Rate"
"in_filter": 0, },
"in_global_search": 0, {
"in_list_view": 0, "fieldname": "base_amount",
"in_standard_filter": 0, "fieldtype": "Currency",
"label": "Basic Rate", "label": "Amount (Company Currency)",
"length": 0, "options": "Company:company:default_currency",
"no_copy": 0, "print_hide": 1,
"oldfieldname": "basic_rate", "read_only": 1,
"oldfieldtype": "Currency", "reqd": 1
"options": "Company:company:default_currency", },
"permlevel": 0, {
"print_hide": 1, "fieldname": "column_break_16",
"print_hide_if_no_value": 0, "fieldtype": "Column Break"
"read_only": 0, },
"remember_last_selected_value": 0, {
"report_hide": 0, "fieldname": "amount",
"reqd": 0, "fieldtype": "Currency",
"search_index": 0, "in_list_view": 1,
"set_only_once": 0, "label": "Amount",
"translatable": 0, "options": "currency",
"unique": 0 "read_only": 1,
"reqd": 1
},
{
"fieldname": "base_rate",
"fieldtype": "Currency",
"label": "Rate (Company Currency)",
"oldfieldname": "basic_rate",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1,
"reqd": 1
} }
], ],
"has_web_view": 0, "idx": 1,
"hide_heading": 0, "istable": 1,
"hide_toolbar": 0, "links": [],
"idx": 1, "modified": "2021-07-30 16:39:09.775720",
"image_view": 0, "modified_by": "Administrator",
"in_create": 0, "module": "CRM",
"is_submittable": 0, "name": "Opportunity Item",
"issingle": 0, "owner": "Administrator",
"istable": 1, "permissions": [],
"max_attachments": 0, "sort_field": "modified",
"modified": "2018-12-28 15:43:09.382012", "sort_order": "DESC",
"modified_by": "Administrator", "track_changes": 1
"module": "CRM",
"name": "Opportunity Item",
"owner": "Administrator",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"track_changes": 1,
"track_seen": 0,
"track_views": 0
} }

1
erpnext/patches.txt

@ -304,3 +304,4 @@ erpnext.patches.v13_0.set_operation_time_based_on_operating_cost
erpnext.patches.v13_0.validate_options_for_data_field erpnext.patches.v13_0.validate_options_for_data_field
erpnext.patches.v13_0.create_gst_payment_entry_fields erpnext.patches.v13_0.create_gst_payment_entry_fields
erpnext.patches.v14_0.delete_shopify_doctypes erpnext.patches.v14_0.delete_shopify_doctypes
erpnext.patches.v14_0.update_opportunity_currency_fields

36
erpnext/patches/v14_0/update_opportunity_currency_fields.py

@ -0,0 +1,36 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt
import erpnext
from erpnext.setup.utils import get_exchange_rate
def execute():
frappe.reload_doc('crm', 'doctype', 'opportunity')
frappe.reload_doc('crm', 'doctype', 'opportunity_item')
opportunities = frappe.db.get_list('Opportunity', filters={
'opportunity_amount': ['>', 0]
}, fields=['name', 'company', 'currency', 'opportunity_amount'])
for opportunity in opportunities:
company_currency = erpnext.get_company_currency(opportunity.company)
# base total and total will be 0 only since item table did not have amount field earlier
if opportunity.currency != company_currency:
conversion_rate = get_exchange_rate(opportunity.currency, company_currency)
base_opportunity_amount = flt(conversion_rate) * flt(opportunity.opportunity_amount)
grand_total = flt(opportunity.opportunity_amount)
base_grand_total = flt(conversion_rate) * flt(opportunity.opportunity_amount)
else:
conversion_rate = 1
base_opportunity_amount = grand_total = base_grand_total = flt(opportunity.opportunity_amount)
frappe.db.set_value('Opportunity', opportunity.name, {
'conversion_rate': conversion_rate,
'base_opportunity_amount': base_opportunity_amount,
'grand_total': grand_total,
'base_grand_total': base_grand_total
}, update_modified=False)
Loading…
Cancel
Save