Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73666982c7 | ||
|
|
48bd1965e4 | ||
|
|
ab84579b0e | ||
|
|
8064792b8c | ||
|
|
fe6c96cab9 | ||
|
|
f8fa3860d9 | ||
|
|
d8a7abcd02 | ||
|
|
5bb9de8614 | ||
|
|
0fd50e0426 | ||
|
|
bdfc300896 | ||
|
|
14292456cf | ||
|
|
24d67c35b7 | ||
|
|
8d71fcb948 | ||
|
|
2945e604aa | ||
|
|
ea085b3a76 | ||
|
|
611966c139 | ||
|
|
8eca908365 | ||
|
|
09d5ddc42b | ||
|
|
abd53b114c | ||
|
|
b1e932a6f8 | ||
|
|
e6a3e6beb7 | ||
|
|
239974c73e | ||
|
|
27ecb54b8c | ||
|
|
6b4b80a4a4 | ||
|
|
68225bbcad | ||
|
|
b549287b94 | ||
|
|
12c3e5dfd6 | ||
|
|
c908add82e | ||
|
|
c74f0f3530 | ||
|
|
2e5a358e96 | ||
|
|
01f8833bd1 | ||
|
|
c5a0c22352 | ||
|
|
b22cbb3122 | ||
|
|
f4a9e52cbe | ||
|
|
24e1786e49 | ||
|
|
5399891b25 | ||
|
|
1b8670b263 | ||
|
|
371d124a0e | ||
|
|
3302ed4658 | ||
|
|
5271ce36de | ||
|
|
88bab1e3ad | ||
|
|
6ec804d77f | ||
|
|
5cced71ce4 | ||
|
|
aea8773503 |
26
.github/workflows/backport.yml
vendored
Normal file
26
.github/workflows/backport.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: Backport
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- closed
|
||||
- labeled
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: "frappe/backport"
|
||||
path: ./actions
|
||||
ref: develop
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: Run backport
|
||||
uses: ./actions/backport
|
||||
with:
|
||||
token: ${{secrets.BACKPORT_BOT_TOKEN}}
|
||||
labelsToAdd: "backport"
|
||||
title: "{{originalTitle}}"
|
||||
@@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '12.23.0'
|
||||
__version__ = '12.24.0'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -81,10 +81,11 @@ class ExchangeRateRevaluation(Document):
|
||||
sum(debit) - sum(credit) as balance
|
||||
from `tabGL Entry`
|
||||
where account in (%s)
|
||||
group by account, party_type, party
|
||||
and posting_date <= %s
|
||||
group by account, NULLIF(party_type,''), NULLIF(party,'')
|
||||
having sum(debit) != sum(credit)
|
||||
order by account
|
||||
""" % ', '.join(['%s']*len(accounts)), tuple(accounts), as_dict=1)
|
||||
""" % (', '.join(['%s']*len(accounts)), '%s'), tuple(accounts + [self.posting_date]), as_dict=1)
|
||||
|
||||
return account_details
|
||||
|
||||
@@ -124,9 +125,9 @@ class ExchangeRateRevaluation(Document):
|
||||
"party_type": d.get("party_type"),
|
||||
"party": d.get("party"),
|
||||
"account_currency": d.get("account_currency"),
|
||||
"balance": d.get("balance_in_account_currency"),
|
||||
dr_or_cr: abs(d.get("balance_in_account_currency")),
|
||||
"exchange_rate":d.get("new_exchange_rate"),
|
||||
"balance": flt(d.get("balance_in_account_currency"), d.precision("balance_in_account_currency")),
|
||||
dr_or_cr: flt(abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency")),
|
||||
"exchange_rate": flt(d.get("new_exchange_rate"), d.precision("new_exchange_rate")),
|
||||
"reference_type": "Exchange Rate Revaluation",
|
||||
"reference_name": self.name,
|
||||
})
|
||||
@@ -135,9 +136,9 @@ class ExchangeRateRevaluation(Document):
|
||||
"party_type": d.get("party_type"),
|
||||
"party": d.get("party"),
|
||||
"account_currency": d.get("account_currency"),
|
||||
"balance": d.get("balance_in_account_currency"),
|
||||
reverse_dr_or_cr: abs(d.get("balance_in_account_currency")),
|
||||
"exchange_rate": d.get("current_exchange_rate"),
|
||||
"balance": flt(d.get("balance_in_account_currency"), d.precision("balance_in_account_currency")),
|
||||
reverse_dr_or_cr: flt(abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency")),
|
||||
"exchange_rate": flt(d.get("current_exchange_rate"), d.precision("current_exchange_rate")),
|
||||
"reference_type": "Exchange Rate Revaluation",
|
||||
"reference_name": self.name
|
||||
})
|
||||
@@ -166,9 +167,9 @@ def get_account_details(account, company, posting_date, party_type=None, party=N
|
||||
|
||||
account_details = {}
|
||||
company_currency = erpnext.get_company_currency(company)
|
||||
balance = get_balance_on(account, party_type=party_type, party=party, in_account_currency=False)
|
||||
balance = get_balance_on(account, date=posting_date, party_type=party_type, party=party, in_account_currency=False)
|
||||
if balance:
|
||||
balance_in_account_currency = get_balance_on(account, party_type=party_type, party=party)
|
||||
balance_in_account_currency = get_balance_on(account, date=posting_date, party_type=party_type, party=party)
|
||||
current_exchange_rate = balance / balance_in_account_currency if balance_in_account_currency else 0
|
||||
new_exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date)
|
||||
new_balance_in_base_currency = balance_in_account_currency * new_exchange_rate
|
||||
|
||||
@@ -593,12 +593,22 @@ frappe.ui.form.on('Payment Entry', {
|
||||
{fieldtype:"Column Break"},
|
||||
{fieldtype:"Float", label: __("Less Than Amount"), fieldname:"outstanding_amt_less_than"},
|
||||
{fieldtype:"Section Break"},
|
||||
{fieldtype:"Link", label:__("Cost Center"), fieldname:"cost_center", options:"Cost Center",
|
||||
"get_query": function() {
|
||||
return {
|
||||
"filters": {"company": frm.doc.company}
|
||||
}
|
||||
}
|
||||
},
|
||||
{fieldtype:"Column Break"},
|
||||
{fieldtype:"Section Break"},
|
||||
{fieldtype:"Check", label: __("Allocate Payment Amount"), fieldname:"allocate_payment_amount", default:1},
|
||||
];
|
||||
|
||||
frappe.prompt(fields, function(filters){
|
||||
frappe.flags.allocate_payment_amount = true;
|
||||
frm.events.validate_filters_data(frm, filters);
|
||||
frm.doc.cost_center = filters.cost_center;
|
||||
frm.events.get_outstanding_documents(frm, filters);
|
||||
}, __("Filters"), __("Get Outstanding Documents"));
|
||||
},
|
||||
@@ -1041,18 +1051,10 @@ frappe.ui.form.on('Payment Entry', {
|
||||
},
|
||||
callback: function(r, rt) {
|
||||
if(r.message) {
|
||||
frappe.run_serially([
|
||||
() => {
|
||||
|
||||
frm.set_value("paid_from_account_balance", r.message.paid_from_account_balance);
|
||||
frm.set_value("paid_to_account_balance", r.message.paid_to_account_balance);
|
||||
frm.set_value("party_balance", r.message.party_balance);
|
||||
},
|
||||
() => {
|
||||
if(frm.doc.payment_type != "Internal") {
|
||||
frm.clear_table("references");
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ def make_entry(args, adv_adj, update_outstanding, from_repost=False):
|
||||
gle.submit()
|
||||
|
||||
def validate_account_for_perpetual_inventory(gl_map):
|
||||
if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)):
|
||||
if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)) and gl_map[0].voucher_type=="Journal Entry":
|
||||
account_list = [gl_entries.account for gl_entries in gl_map]
|
||||
|
||||
aii_accounts = [d.name for d in frappe.get_all("Account",
|
||||
@@ -160,13 +160,12 @@ def validate_account_for_perpetual_inventory(gl_map):
|
||||
account_bal, stock_bal, warehouse_list = get_stock_and_account_balance(account,
|
||||
gl_map[0].posting_date, gl_map[0].company)
|
||||
|
||||
if gl_map[0].voucher_type=="Journal Entry":
|
||||
# In case of Journal Entry, there are no corresponding SL entries,
|
||||
# hence deducting currency amount
|
||||
account_bal -= flt(gl_map[0].debit) - flt(gl_map[0].credit)
|
||||
if account_bal == stock_bal:
|
||||
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
|
||||
.format(account), StockAccountInvalidTransaction)
|
||||
# In case of Journal Entry, there are no corresponding SL entries,
|
||||
# hence deducting currency amount
|
||||
account_bal -= flt(gl_map[0].debit) - flt(gl_map[0].credit)
|
||||
if account_bal == stock_bal:
|
||||
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
|
||||
.format(account), StockAccountInvalidTransaction)
|
||||
|
||||
# This has been comment for a temporary, will add this code again on release of immutable ledger
|
||||
# elif account_bal != stock_bal:
|
||||
@@ -294,7 +293,8 @@ def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
|
||||
select account, posting_date, party_type, party, cost_center, fiscal_year,voucher_type,
|
||||
voucher_no, against_voucher_type, against_voucher, cost_center, company
|
||||
from `tabGL Entry`
|
||||
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no), as_dict=True)
|
||||
where voucher_type=%s and voucher_no=%s
|
||||
for update""", (voucher_type, voucher_no), as_dict=True)
|
||||
|
||||
if gl_entries:
|
||||
validate_accounting_period(gl_entries)
|
||||
|
||||
13
erpnext/change_log/v12/v12_24_0.md
Normal file
13
erpnext/change_log/v12/v12_24_0.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## Version 12.24.0 Release Notes
|
||||
|
||||
### Fixes & Enhancements
|
||||
- Sales order qty update fails in "Update Items" button ([#26992](https://github.com/frappe/erpnext/pull/26992))
|
||||
- Speed up validate_account_for_perpetual_inventory ([#26730](https://github.com/frappe/erpnext/pull/26730))
|
||||
- Deadlock while doing payment reconciliation ([#26674](https://github.com/frappe/erpnext/pull/26674))
|
||||
- Remove incorrect condition in GLE comparison ([#26713](https://github.com/frappe/erpnext/pull/26713))
|
||||
- Cannot cancel invoice if IRN cancelled on portal ([#26880](https://github.com/frappe/erpnext/pull/26880))
|
||||
- Item name is missing into job card ([#26956](https://github.com/frappe/erpnext/pull/26956))
|
||||
- Removed company filter for Loan Type ([#26463](https://github.com/frappe/erpnext/pull/26463))
|
||||
- Exchange rate revaluation posting date and precision fixes ([#26629](https://github.com/frappe/erpnext/pull/26629))
|
||||
- Fixed clearing issue of payment references on setting cost center ([#26548](https://github.com/frappe/erpnext/pull/26548))
|
||||
- Increase number of supported currency exchanges ([#25722](https://github.com/frappe/erpnext/pull/25722))
|
||||
@@ -1312,7 +1312,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
||||
qty_unchanged = prev_qty == new_qty
|
||||
uom_unchanged = prev_uom == new_uom
|
||||
conversion_factor_unchanged = prev_con_fac == new_con_fac
|
||||
date_unchanged = prev_date == new_date if prev_date and new_date else False # in case of delivery note etc
|
||||
date_unchanged = prev_date == getdate(new_date) if prev_date and new_date else False # in case of delivery note etc
|
||||
if rate_unchanged and qty_unchanged and conversion_factor_unchanged and uom_unchanged and date_unchanged:
|
||||
continue
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import flt, comma_or, nowdate, getdate
|
||||
from frappe.utils import flt, comma_or, nowdate, getdate, now
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
@@ -307,10 +307,14 @@ class StatusUpdater(Document):
|
||||
target.notify_update()
|
||||
|
||||
def _update_modified(self, args, update_modified):
|
||||
args['update_modified'] = ''
|
||||
if update_modified:
|
||||
args['update_modified'] = ', modified = now(), modified_by = {0}'\
|
||||
.format(frappe.db.escape(frappe.session.user))
|
||||
if not update_modified:
|
||||
args['update_modified'] = ''
|
||||
return
|
||||
|
||||
args['update_modified'] = ', modified = {0}, modified_by = {1}'.format(
|
||||
frappe.db.escape(now()),
|
||||
frappe.db.escape(frappe.session.user)
|
||||
)
|
||||
|
||||
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
|
||||
ref_fieldname = frappe.scrub(ref_dt)
|
||||
|
||||
@@ -418,7 +418,7 @@ def compare_existing_and_expected_gle(existing_gle, expected_gle):
|
||||
for e in existing_gle:
|
||||
if entry.account == e.account:
|
||||
account_existed = True
|
||||
if entry.account == e.account and entry.against_account == e.against_account \
|
||||
if entry.account == e.account \
|
||||
and (not entry.cost_center or not e.cost_center or entry.cost_center == e.cost_center) \
|
||||
and (entry.debit != e.debit or entry.credit != e.credit):
|
||||
matched = False
|
||||
|
||||
@@ -15,15 +15,6 @@ frappe.ui.form.on('Loan', {
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("loan_type", function () {
|
||||
return {
|
||||
"filters": {
|
||||
"docstatus": 1,
|
||||
"company": frm.doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("interest_income_account", function () {
|
||||
return {
|
||||
"filters": {
|
||||
|
||||
@@ -7,13 +7,6 @@ frappe.ui.form.on('Loan Application', {
|
||||
refresh: function(frm) {
|
||||
frm.trigger("toggle_fields");
|
||||
frm.trigger("add_toolbar_buttons");
|
||||
frm.set_query('loan_type', () => {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
repayment_method: function(frm) {
|
||||
frm.doc.repayment_amount = frm.doc.repayment_periods = ""
|
||||
|
||||
@@ -5,10 +5,17 @@ frappe.ui.form.on('Salary Component', {
|
||||
setup: function(frm) {
|
||||
frm.set_query("default_account", "accounts", function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
|
||||
var root_type = "Liability";
|
||||
if (frm.doc.type == "Deduction") {
|
||||
root_type = "Expense";
|
||||
}
|
||||
|
||||
return {
|
||||
filters: {
|
||||
"is_group": 0,
|
||||
"company": d.company
|
||||
"company": d.company,
|
||||
"root_type": root_type
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -89,6 +89,7 @@ def execute(filters=None):
|
||||
"amount": salary.net_pay,
|
||||
}
|
||||
data.append(row)
|
||||
|
||||
return columns, data
|
||||
|
||||
def get_bank_accounts():
|
||||
@@ -110,7 +111,7 @@ def get_payroll_entries(accounts, filters):
|
||||
entries = get_all("Payroll Entry", payroll_filter, ["name", "payment_account"])
|
||||
|
||||
payment_accounts = [d.payment_account for d in entries]
|
||||
set_company_account(payment_accounts, entries)
|
||||
entries = set_company_account(payment_accounts, entries)
|
||||
return entries
|
||||
|
||||
def get_salary_slips(payroll_entries):
|
||||
|
||||
@@ -107,6 +107,8 @@
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.production_item",
|
||||
"fetch_from": "production_item.item_name",
|
||||
"fetch_if_empty": 1,
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Item Name",
|
||||
@@ -470,7 +472,7 @@
|
||||
"image_field": "image",
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2019-12-04 11:20:04.695123",
|
||||
"modified": "2021-08-16 11:20:04.695123",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Work Order",
|
||||
|
||||
@@ -686,3 +686,4 @@ erpnext.patches.v12_0.purchase_receipt_status
|
||||
erpnext.patches.v12_0.add_company_link_to_einvoice_settings
|
||||
erpnext.patches.v12_0.add_document_type_field_for_italy_einvoicing
|
||||
erpnext.patches.v12_0.create_taxable_value_field_in_purchase_invoice
|
||||
erpnext.patches.v12_0.show_einvoice_irn_cancelled_field
|
||||
12
erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py
Normal file
12
erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
company = frappe.get_all('Company', filters = {'country': 'India'})
|
||||
if not company:
|
||||
return
|
||||
|
||||
irn_cancelled_field = frappe.db.exists('Custom Field', {'dt': 'Sales Invoice', 'fieldname': 'irn_cancelled'})
|
||||
if irn_cancelled_field:
|
||||
frappe.db.set_value('Custom Field', irn_cancelled_field, 'depends_on', 'eval: doc.irn')
|
||||
frappe.db.set_value('Custom Field', irn_cancelled_field, 'read_only', 0)
|
||||
@@ -73,9 +73,6 @@ class Task(NestedSet):
|
||||
if (self.progress or 0) > 100:
|
||||
frappe.throw(_("Progress % for a task cannot be more than 100."))
|
||||
|
||||
if self.progress == 100:
|
||||
self.status = 'Completed'
|
||||
|
||||
if self.status == 'Completed':
|
||||
self.progress = 100
|
||||
|
||||
|
||||
@@ -414,7 +414,7 @@ def make_custom_fields(update=True):
|
||||
dict(fieldname='ack_date', label='Ack. Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_no', no_copy=1, print_hide=1),
|
||||
|
||||
dict(fieldname='irn_cancelled', label='IRN Cancelled', fieldtype='Check', no_copy=1, print_hide=1,
|
||||
depends_on='eval:(doc.irn_cancelled === 1)', read_only=1, allow_on_submit=1, insert_after='customer'),
|
||||
depends_on='eval: doc.irn', allow_on_submit=1, insert_after='customer'),
|
||||
|
||||
dict(fieldname='eway_bill_cancelled', label='E-Way Bill Cancelled', fieldtype='Check', no_copy=1, print_hide=1,
|
||||
depends_on='eval:(doc.eway_bill_cancelled === 1)', read_only=1, allow_on_submit=1, insert_after='customer'),
|
||||
|
||||
@@ -62,12 +62,12 @@ class TestCurrencyExchange(unittest.TestCase):
|
||||
|
||||
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, should be fetched from fixer.io
|
||||
|
||||
# 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.894)
|
||||
self.assertEqual(flt(exchange_rate, 3), 66.999)
|
||||
|
||||
def test_exchange_rate_strict(self):
|
||||
# strict currency settings
|
||||
@@ -77,28 +77,17 @@ class TestCurrencyExchange(unittest.TestCase):
|
||||
exchange_rate = get_exchange_rate("USD", "INR", "2016-01-01", "for_buying")
|
||||
self.assertEqual(exchange_rate, 60.0)
|
||||
|
||||
# Will fetch from fixer.io
|
||||
self.clear_cache()
|
||||
exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15", "for_buying")
|
||||
self.assertEqual(flt(exchange_rate, 3), 67.79)
|
||||
self.assertEqual(flt(exchange_rate, 3), 67.235)
|
||||
|
||||
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, should be fetched from fixer.io
|
||||
# Exchange rate as on 15th Dec, 2015
|
||||
self.clear_cache()
|
||||
exchange_rate = get_exchange_rate("USD", "INR", "2015-12-15", "for_buying")
|
||||
self.assertEqual(flt(exchange_rate, 3), 66.894)
|
||||
|
||||
exchange_rate = get_exchange_rate("INR", "NGN", "2016-01-10", "for_selling")
|
||||
self.assertEqual(exchange_rate, 65.1)
|
||||
|
||||
# NGN is not available on fixer.io so these should return 0
|
||||
exchange_rate = get_exchange_rate("INR", "NGN", "2016-01-09", "for_selling")
|
||||
self.assertEqual(exchange_rate, 0)
|
||||
|
||||
exchange_rate = get_exchange_rate("INR", "NGN", "2016-01-11", "for_selling")
|
||||
self.assertEqual(exchange_rate, 0)
|
||||
self.assertEqual(flt(exchange_rate, 3), 66.999)
|
||||
|
||||
def test_exchange_rate_strict_switched(self):
|
||||
# Start with allow_stale is True
|
||||
@@ -111,4 +100,4 @@ class TestCurrencyExchange(unittest.TestCase):
|
||||
# Will fetch from fixer.io
|
||||
self.clear_cache()
|
||||
exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15", "for_buying")
|
||||
self.assertEqual(flt(exchange_rate, 3), 67.79)
|
||||
self.assertEqual(flt(exchange_rate, 3), 67.235)
|
||||
|
||||
@@ -175,9 +175,9 @@ def install(country=None):
|
||||
]},
|
||||
|
||||
# Issue Priority
|
||||
{'doctype': 'Issue Priority', 'name': _('Low')},
|
||||
{'doctype': 'Issue Priority', 'name': _('Medium')},
|
||||
{'doctype': 'Issue Priority', 'name': _('High')},
|
||||
{'doctype': 'Issue Priority', 'name': 'Low'},
|
||||
{'doctype': 'Issue Priority', 'name': 'Medium'},
|
||||
{'doctype': 'Issue Priority', 'name': 'High'},
|
||||
|
||||
#Job Applicant Source
|
||||
{'doctype': 'Job Applicant Source', 'source_name': _('Website Listing')},
|
||||
|
||||
@@ -93,20 +93,21 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No
|
||||
|
||||
try:
|
||||
cache = frappe.cache()
|
||||
key = "currency_exchange_rate_{0}:{1}:{2}".format(transaction_date,from_currency, to_currency)
|
||||
key = "currency_exchange_rate_{0}:{1}:{2}".format(transaction_date, from_currency, to_currency)
|
||||
value = cache.get(key)
|
||||
|
||||
if not value:
|
||||
import requests
|
||||
api_url = "https://frankfurter.app/{0}".format(transaction_date)
|
||||
api_url = "https://api.exchangerate.host/convert"
|
||||
response = requests.get(api_url, params={
|
||||
"base": from_currency,
|
||||
"symbols": to_currency
|
||||
"date": transaction_date,
|
||||
"from": from_currency,
|
||||
"to": to_currency
|
||||
})
|
||||
# expire in 6 hours
|
||||
response.raise_for_status()
|
||||
value = response.json()["rates"][to_currency]
|
||||
cache.setex(key, value, 6 * 60 * 60)
|
||||
value = response.json()["result"]
|
||||
cache.setex(name=key, time=21600, value=flt(value))
|
||||
return flt(value)
|
||||
except:
|
||||
frappe.log_error(title="Get Exchange Rate")
|
||||
|
||||
@@ -206,11 +206,11 @@ def update_cart_address(address_type, address_name):
|
||||
if address_type.lower() == "billing":
|
||||
quotation.customer_address = address_name
|
||||
quotation.address_display = address_display
|
||||
quotation.shipping_address_name == quotation.shipping_address_name or address_name
|
||||
quotation.shipping_address_name = quotation.shipping_address_name or address_name
|
||||
elif address_type.lower() == "shipping":
|
||||
quotation.shipping_address_name = address_name
|
||||
quotation.shipping_address = address_display
|
||||
quotation.customer_address == quotation.customer_address or address_name
|
||||
quotation.customer_address = quotation.customer_address or address_name
|
||||
|
||||
apply_cart_settings(quotation=quotation)
|
||||
|
||||
@@ -279,7 +279,7 @@ def update_party(fullname, company_name=None, mobile_no=None, phone=None):
|
||||
party = get_party()
|
||||
|
||||
party.customer_name = company_name or fullname
|
||||
party.customer_type == "Company" if company_name else "Individual"
|
||||
party.customer_type = "Company" if company_name else "Individual"
|
||||
|
||||
contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user})
|
||||
contact = frappe.get_doc("Contact", contact_name)
|
||||
|
||||
@@ -22,7 +22,7 @@ frappe.ui.form.on("Purchase Receipt", {
|
||||
frappe.set_route("Form", lcv.doctype, lcv.name);
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
frm.custom_make_buttons = {
|
||||
'Stock Entry': 'Return',
|
||||
'Purchase Invoice': 'Purchase Invoice'
|
||||
@@ -34,7 +34,7 @@ frappe.ui.form.on("Purchase Receipt", {
|
||||
filters: {'company': frm.doc.company }
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
onload: function(frm) {
|
||||
erpnext.queries.setup_queries(frm, "Warehouse", function() {
|
||||
@@ -107,6 +107,8 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
|
||||
message: __("Please Select a Supplier")
|
||||
});
|
||||
}
|
||||
|
||||
me.frm.doc.taxes = [];
|
||||
erpnext.utils.map_current_doc({
|
||||
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_receipt",
|
||||
source_doctype: "Purchase Order",
|
||||
|
||||
@@ -15,8 +15,6 @@ from six import iteritems
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
|
||||
validate_filters(filters)
|
||||
|
||||
from_date = filters.get('from_date')
|
||||
to_date = filters.get('to_date')
|
||||
|
||||
@@ -293,12 +291,6 @@ def get_item_reorder_details(items):
|
||||
|
||||
return dict((d.parent + d.warehouse, d) for d in item_reorder_details)
|
||||
|
||||
def validate_filters(filters):
|
||||
if not (filters.get("item_code") or filters.get("warehouse")):
|
||||
sle_count = flt(frappe.db.sql("""select count(name) from `tabStock Ledger Entry`""")[0][0])
|
||||
if sle_count > 500000:
|
||||
frappe.throw(_("Please set filter based on Item or Warehouse due to a large amount of entries."))
|
||||
|
||||
def get_variants_attributes():
|
||||
'''Return all item variant attributes.'''
|
||||
return [i.name for i in frappe.get_all('Item Attribute')]
|
||||
|
||||
@@ -316,13 +316,16 @@ def update_included_uom_in_report(columns, result, include_uom, conversion_facto
|
||||
for row_idx, row in enumerate(result):
|
||||
data = row.items() if is_dict_obj else enumerate(row)
|
||||
for key, value in data:
|
||||
if key not in convertible_columns or not conversion_factors[row_idx-1]:
|
||||
if key not in convertible_columns:
|
||||
continue
|
||||
# If no conversion factor for the UOM, defaults to 1
|
||||
if not conversion_factors[row_idx]:
|
||||
conversion_factors[row_idx] = 1
|
||||
|
||||
if convertible_columns.get(key) == 'rate':
|
||||
new_value = flt(value) * conversion_factors[row_idx-1]
|
||||
new_value = flt(value) * conversion_factors[row_idx]
|
||||
else:
|
||||
new_value = flt(value) / conversion_factors[row_idx-1]
|
||||
new_value = flt(value) / conversion_factors[row_idx]
|
||||
|
||||
if not is_dict_obj:
|
||||
row.insert(key+1, new_value)
|
||||
@@ -370,4 +373,4 @@ def add_additional_uom_columns(columns, result, include_uom, conversion_factors)
|
||||
else:
|
||||
row[data.converted_col] = flt(value_before_conversion) / conversion_factor
|
||||
|
||||
result[row_idx] = row
|
||||
result[row_idx] = row
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
braintree==3.57.1
|
||||
frappe
|
||||
# frappe # https://github.com/frappe/frappe is installed during bench-init
|
||||
gocardless-pro==1.11.0
|
||||
googlemaps==3.1.1
|
||||
pandas==0.24.2
|
||||
plaid-python>=7.0.0
|
||||
plaid-python~=7.2.1
|
||||
PyGithub==1.44.1
|
||||
python-stdnum==1.12
|
||||
Unidecode==1.1.1
|
||||
|
||||
Reference in New Issue
Block a user