mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-06 13:49:13 +00:00
Merge branch 'develop' into supplier-quotn-comparison
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
ERPNext as a monolith includes the following areas for managing businesses:
|
ERPNext as a monolith includes the following areas for managing businesses:
|
||||||
|
|
||||||
1. [Accounting](https://erpnext.com/open-source-accounting)
|
1. [Accounting](https://erpnext.com/open-source-accounting)
|
||||||
1. [Inventory](https://erpnext.com/distribution/inventory-management-system)
|
1. [Warehouse Management](https://erpnext.com/distribution/warehouse-management-system)
|
||||||
1. [CRM](https://erpnext.com/open-source-crm)
|
1. [CRM](https://erpnext.com/open-source-crm)
|
||||||
1. [Sales](https://erpnext.com/open-source-sales-purchase)
|
1. [Sales](https://erpnext.com/open-source-sales-purchase)
|
||||||
1. [Purchase](https://erpnext.com/open-source-sales-purchase)
|
1. [Purchase](https://erpnext.com/open-source-sales-purchase)
|
||||||
|
|||||||
@@ -38,8 +38,8 @@
|
|||||||
"reqd": 1
|
"reqd": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2020-06-18 20:27:42.615842",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "ahmad@havenir.com",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Item Tax Template",
|
"name": "Item Tax Template",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
|||||||
@@ -45,11 +45,11 @@
|
|||||||
],
|
],
|
||||||
"icon": "fa fa-credit-card",
|
"icon": "fa fa-credit-card",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2019-08-14 14:58:42.079115",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "sammish.thundiyil@gmail.com",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Mode of Payment",
|
"name": "Mode of Payment",
|
||||||
"owner": "harshada@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"create": 1,
|
"create": 1,
|
||||||
|
|||||||
@@ -291,11 +291,11 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-08-21 16:15:49.089450",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Period Closing Voucher",
|
"name": "Period Closing Voucher",
|
||||||
"owner": "jai@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 1,
|
"amend": 1,
|
||||||
|
|||||||
@@ -5,13 +5,14 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import cint
|
from frappe.utils import cint, get_link_to_form
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from erpnext.controllers.status_updater import StatusUpdater
|
from erpnext.controllers.status_updater import StatusUpdater
|
||||||
|
|
||||||
class POSOpeningEntry(StatusUpdater):
|
class POSOpeningEntry(StatusUpdater):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_pos_profile_and_cashier()
|
self.validate_pos_profile_and_cashier()
|
||||||
|
self.validate_payment_method_account()
|
||||||
self.set_status()
|
self.set_status()
|
||||||
|
|
||||||
def validate_pos_profile_and_cashier(self):
|
def validate_pos_profile_and_cashier(self):
|
||||||
@@ -21,5 +22,13 @@ class POSOpeningEntry(StatusUpdater):
|
|||||||
if not cint(frappe.db.get_value("User", self.user, "enabled")):
|
if not cint(frappe.db.get_value("User", self.user, "enabled")):
|
||||||
frappe.throw(_("User {} has been disabled. Please select valid user/cashier".format(self.user)))
|
frappe.throw(_("User {} has been disabled. Please select valid user/cashier".format(self.user)))
|
||||||
|
|
||||||
|
def validate_payment_method_account(self):
|
||||||
|
for d in self.balance_details:
|
||||||
|
account = frappe.db.get_value("Mode of Payment Account",
|
||||||
|
{"parent": d.mode_of_payment, "company": self.company}, "default_account")
|
||||||
|
if not account:
|
||||||
|
frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
|
||||||
|
.format(get_link_to_form("Mode of Payment", mode_of_payment)), title=_("Missing Account"))
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.set_status(update=True)
|
self.set_status(update=True)
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import msgprint, _
|
from frappe import msgprint, _
|
||||||
from frappe.utils import cint, now
|
from frappe.utils import cint, now, get_link_to_form
|
||||||
from six import iteritems
|
from six import iteritems
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ class POSProfile(Document):
|
|||||||
self.validate_default_profile()
|
self.validate_default_profile()
|
||||||
self.validate_all_link_fields()
|
self.validate_all_link_fields()
|
||||||
self.validate_duplicate_groups()
|
self.validate_duplicate_groups()
|
||||||
self.check_default_payment()
|
self.validate_payment_methods()
|
||||||
|
|
||||||
def validate_default_profile(self):
|
def validate_default_profile(self):
|
||||||
for row in self.applicable_for_users:
|
for row in self.applicable_for_users:
|
||||||
@@ -52,14 +52,23 @@ class POSProfile(Document):
|
|||||||
if len(customer_groups) != len(set(customer_groups)):
|
if len(customer_groups) != len(set(customer_groups)):
|
||||||
frappe.throw(_("Duplicate customer group found in the cutomer group table"), title = "Duplicate Customer Group")
|
frappe.throw(_("Duplicate customer group found in the cutomer group table"), title = "Duplicate Customer Group")
|
||||||
|
|
||||||
def check_default_payment(self):
|
def validate_payment_methods(self):
|
||||||
if self.payments:
|
if not self.payments:
|
||||||
default_mode_of_payment = [d.default for d in self.payments if d.default]
|
frappe.throw(_("Payment methods are mandatory. Please add at least one payment method."))
|
||||||
if not default_mode_of_payment:
|
|
||||||
frappe.throw(_("Set default mode of payment"))
|
|
||||||
|
|
||||||
if len(default_mode_of_payment) > 1:
|
default_mode_of_payment = [d.default for d in self.payments if d.default]
|
||||||
frappe.throw(_("Multiple default mode of payment is not allowed"))
|
if not default_mode_of_payment:
|
||||||
|
frappe.throw(_("Please select a default mode of payment"))
|
||||||
|
|
||||||
|
if len(default_mode_of_payment) > 1:
|
||||||
|
frappe.throw(_("You can only select one mode of payment as default"))
|
||||||
|
|
||||||
|
for d in self.payments:
|
||||||
|
account = frappe.db.get_value("Mode of Payment Account",
|
||||||
|
{"parent": d.mode_of_payment, "company": self.company}, "default_account")
|
||||||
|
if not account:
|
||||||
|
frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
|
||||||
|
.format(get_link_to_form("Mode of Payment", mode_of_payment)), title=_("Missing Account"))
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
self.set_defaults()
|
self.set_defaults()
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ frappe.ui.form.on('POS Settings', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
get_invoice_fields: function(frm) {
|
get_invoice_fields: function(frm) {
|
||||||
frappe.model.with_doctype("Sales Invoice", () => {
|
frappe.model.with_doctype("POS Invoice", () => {
|
||||||
var fields = $.map(frappe.get_doc("DocType", "Sales Invoice").fields, function(d) {
|
var fields = $.map(frappe.get_doc("DocType", "POS Invoice").fields, function(d) {
|
||||||
if (frappe.model.no_value_type.indexOf(d.fieldtype) === -1 ||
|
if (frappe.model.no_value_type.indexOf(d.fieldtype) === -1 ||
|
||||||
d.fieldtype === 'Table') {
|
['Table', 'Button'].includes(d.fieldtype)) {
|
||||||
return { label: d.label + ' (' + d.fieldtype + ')', value: d.fieldname };
|
return { label: d.label + ' (' + d.fieldtype + ')', value: d.fieldname };
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@@ -25,7 +25,7 @@ frappe.ui.form.on('POS Settings', {
|
|||||||
frappe.ui.form.on("POS Field", {
|
frappe.ui.form.on("POS Field", {
|
||||||
fieldname: function(frm, doctype, name) {
|
fieldname: function(frm, doctype, name) {
|
||||||
var doc = frappe.get_doc(doctype, name);
|
var doc = frappe.get_doc(doctype, name);
|
||||||
var df = $.map(frappe.get_doc("DocType", "Sales Invoice").fields, function(d) {
|
var df = $.map(frappe.get_doc("DocType", "POS Invoice").fields, function(d) {
|
||||||
return doc.fieldname == d.fieldname ? d : null;
|
return doc.fieldname == d.fieldname ? d : null;
|
||||||
})[0];
|
})[0];
|
||||||
|
|
||||||
|
|||||||
@@ -210,7 +210,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-03-12 14:53:47.679439",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Taxes and Charges",
|
"name": "Purchase Taxes and Charges",
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Taxes and Charges Template",
|
"name": "Purchase Taxes and Charges Template",
|
||||||
"owner": "wasim@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"email": 1,
|
"email": 1,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, erpnext
|
import frappe, erpnext
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate
|
from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate, get_link_to_form
|
||||||
from frappe import _, msgprint, throw
|
from frappe import _, msgprint, throw
|
||||||
from erpnext.accounts.party import get_party_account, get_due_date
|
from erpnext.accounts.party import get_party_account, get_due_date
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
@@ -1372,7 +1372,7 @@ def get_bank_cash_account(mode_of_payment, company):
|
|||||||
{"parent": mode_of_payment, "company": company}, "default_account")
|
{"parent": mode_of_payment, "company": company}, "default_account")
|
||||||
if not account:
|
if not account:
|
||||||
frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
|
frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
|
||||||
.format(mode_of_payment))
|
.format(get_link_to_form("Mode of Payment", mode_of_payment)), title=_("Missing Account"))
|
||||||
return {
|
return {
|
||||||
"account": account
|
"account": account
|
||||||
}
|
}
|
||||||
@@ -1612,18 +1612,16 @@ def update_multi_mode_option(doc, pos_profile):
|
|||||||
payment.type = payment_mode.type
|
payment.type = payment_mode.type
|
||||||
|
|
||||||
doc.set('payments', [])
|
doc.set('payments', [])
|
||||||
if not pos_profile or not pos_profile.get('payments'):
|
|
||||||
for payment_mode in get_all_mode_of_payments(doc):
|
|
||||||
append_payment(payment_mode)
|
|
||||||
return
|
|
||||||
|
|
||||||
for pos_payment_method in pos_profile.get('payments'):
|
for pos_payment_method in pos_profile.get('payments'):
|
||||||
pos_payment_method = pos_payment_method.as_dict()
|
pos_payment_method = pos_payment_method.as_dict()
|
||||||
|
|
||||||
payment_mode = get_mode_of_payment_info(pos_payment_method.mode_of_payment, doc.company)
|
payment_mode = get_mode_of_payment_info(pos_payment_method.mode_of_payment, doc.company)
|
||||||
if payment_mode:
|
if not payment_mode:
|
||||||
payment_mode[0].default = pos_payment_method.default
|
frappe.throw(_("Please set default Cash or Bank account in Mode of Payment {0}")
|
||||||
append_payment(payment_mode[0])
|
.format(get_link_to_form("Mode of Payment", pos_payment_method.mode_of_payment)), title=_("Missing Account"))
|
||||||
|
|
||||||
|
payment_mode[0].default = pos_payment_method.default
|
||||||
|
append_payment(payment_mode[0])
|
||||||
|
|
||||||
def get_all_mode_of_payments(doc):
|
def get_all_mode_of_payments(doc):
|
||||||
return frappe.db.sql("""
|
return frappe.db.sql("""
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ erpnext.accounts.bankReconciliation = class BankReconciliation {
|
|||||||
check_plaid_status() {
|
check_plaid_status() {
|
||||||
const me = this;
|
const me = this;
|
||||||
frappe.db.get_value("Plaid Settings", "Plaid Settings", "enabled", (r) => {
|
frappe.db.get_value("Plaid Settings", "Plaid Settings", "enabled", (r) => {
|
||||||
if (r && r.enabled == "1") {
|
if (r && r.enabled === "1") {
|
||||||
me.plaid_status = "active"
|
me.plaid_status = "active"
|
||||||
} else {
|
} else {
|
||||||
me.plaid_status = "inactive"
|
me.plaid_status = "inactive"
|
||||||
@@ -214,31 +214,35 @@ erpnext.accounts.bankTransactionSync = class bankTransactionSync {
|
|||||||
|
|
||||||
init_config() {
|
init_config() {
|
||||||
const me = this;
|
const me = this;
|
||||||
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.plaid_configuration')
|
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_plaid_configuration')
|
||||||
.then(result => {
|
.then(result => {
|
||||||
me.plaid_env = result.plaid_env;
|
me.plaid_env = result.plaid_env;
|
||||||
me.plaid_public_key = result.plaid_public_key;
|
me.client_name = result.client_name;
|
||||||
me.client_name = result.client_name;
|
me.link_token = result.link_token;
|
||||||
me.sync_transactions()
|
me.sync_transactions();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_transactions() {
|
sync_transactions() {
|
||||||
const me = this;
|
const me = this;
|
||||||
frappe.db.get_value("Bank Account", me.parent.bank_account, "bank", (v) => {
|
frappe.db.get_value("Bank Account", me.parent.bank_account, "bank", (r) => {
|
||||||
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.sync_transactions', {
|
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.sync_transactions', {
|
||||||
bank: v['bank'],
|
bank: r.bank,
|
||||||
bank_account: me.parent.bank_account,
|
bank_account: me.parent.bank_account,
|
||||||
freeze: true
|
freeze: true
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
let result_title = (result.length > 0) ? __("{0} bank transaction(s) created", [result.length]) : __("This bank account is already synchronized")
|
let result_title = (result && result.length > 0)
|
||||||
|
? __("{0} bank transaction(s) created", [result.length])
|
||||||
|
: __("This bank account is already synchronized");
|
||||||
|
|
||||||
let result_msg = `
|
let result_msg = `
|
||||||
<div class="flex justify-center align-center text-muted" style="height: 50vh; display: flex;">
|
<div class="flex justify-center align-center text-muted" style="height: 50vh; display: flex;">
|
||||||
<h5 class="text-muted">${result_title}</h5>
|
<h5 class="text-muted">${result_title}</h5>
|
||||||
</div>`
|
</div>`
|
||||||
|
|
||||||
this.parent.$main_section.append(result_msg)
|
this.parent.$main_section.append(result_msg)
|
||||||
frappe.show_alert({message:__("Bank account '{0}' has been synchronized", [me.parent.bank_account]), indicator:'green'});
|
frappe.show_alert({ message: __("Bank account '{0}' has been synchronized", [me.parent.bank_account]), indicator: 'green' });
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -384,7 +388,7 @@ erpnext.accounts.ReconciliationRow = class ReconciliationRow {
|
|||||||
})
|
})
|
||||||
|
|
||||||
frappe.xcall('erpnext.accounts.page.bank_reconciliation.bank_reconciliation.get_linked_payments',
|
frappe.xcall('erpnext.accounts.page.bank_reconciliation.bank_reconciliation.get_linked_payments',
|
||||||
{bank_transaction: data, freeze:true, freeze_message:__("Finding linked payments")}
|
{ bank_transaction: data, freeze: true, freeze_message: __("Finding linked payments") }
|
||||||
).then((result) => {
|
).then((result) => {
|
||||||
me.make_dialog(result)
|
me.make_dialog(result)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ frappe.query_reports["Accounts Receivable"] = {
|
|||||||
filters: {
|
filters: {
|
||||||
'company': company
|
'company': company
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -617,9 +617,19 @@ class ReceivablePayableReport(object):
|
|||||||
elif party_type_field=="supplier":
|
elif party_type_field=="supplier":
|
||||||
self.add_supplier_filters(conditions, values)
|
self.add_supplier_filters(conditions, values)
|
||||||
|
|
||||||
|
if self.filters.cost_center:
|
||||||
|
self.get_cost_center_conditions(conditions)
|
||||||
|
|
||||||
self.add_accounting_dimensions_filters(conditions, values)
|
self.add_accounting_dimensions_filters(conditions, values)
|
||||||
return " and ".join(conditions), values
|
return " and ".join(conditions), values
|
||||||
|
|
||||||
|
def get_cost_center_conditions(self, conditions):
|
||||||
|
lft, rgt = frappe.db.get_value("Cost Center", self.filters.cost_center, ["lft", "rgt"])
|
||||||
|
cost_center_list = [center.name for center in frappe.get_list("Cost Center", filters = {'lft': (">=", lft), 'rgt': ("<=", rgt)})]
|
||||||
|
|
||||||
|
cost_center_string = '", "'.join(cost_center_list)
|
||||||
|
conditions.append('cost_center in ("{0}")'.format(cost_center_string))
|
||||||
|
|
||||||
def get_order_by_condition(self):
|
def get_order_by_condition(self):
|
||||||
if self.filters.get('group_by_party'):
|
if self.filters.get('group_by_party'):
|
||||||
return "order by party, posting_date"
|
return "order by party, posting_date"
|
||||||
|
|||||||
@@ -252,13 +252,6 @@ frappe.ui.form.on('Asset', {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
available_for_use_date: function(frm) {
|
|
||||||
$.each(frm.doc.finance_books || [], function(i, d) {
|
|
||||||
if(!d.depreciation_start_date) d.depreciation_start_date = frm.doc.available_for_use_date;
|
|
||||||
});
|
|
||||||
refresh_field("finance_books");
|
|
||||||
},
|
|
||||||
|
|
||||||
is_existing_asset: function(frm) {
|
is_existing_asset: function(frm) {
|
||||||
frm.trigger("toggle_reference_doc");
|
frm.trigger("toggle_reference_doc");
|
||||||
// frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation));
|
// frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation));
|
||||||
@@ -438,6 +431,15 @@ frappe.ui.form.on('Asset Finance Book', {
|
|||||||
}
|
}
|
||||||
|
|
||||||
frappe.flags.dont_change_rate = false;
|
frappe.flags.dont_change_rate = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
depreciation_start_date: function(frm, cdt, cdn) {
|
||||||
|
const book = locals[cdt][cdn];
|
||||||
|
if (frm.doc.available_for_use_date && book.depreciation_start_date == frm.doc.available_for_use_date) {
|
||||||
|
frappe.msgprint(__(`Depreciation Posting Date should not be equal to Available for Use Date.`));
|
||||||
|
book.depreciation_start_date = "";
|
||||||
|
frm.refresh_field("finance_books");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
|||||||
import frappe, erpnext, math, json
|
import frappe, erpnext, math, json
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from six import string_types
|
from six import string_types
|
||||||
from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff, month_diff, add_days
|
from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff, month_diff, add_days, get_last_day
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
|
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
|
||||||
from erpnext.assets.doctype.asset.depreciation \
|
from erpnext.assets.doctype.asset.depreciation \
|
||||||
@@ -83,6 +83,11 @@ class Asset(AccountsController):
|
|||||||
if not self.available_for_use_date:
|
if not self.available_for_use_date:
|
||||||
frappe.throw(_("Available for use date is required"))
|
frappe.throw(_("Available for use date is required"))
|
||||||
|
|
||||||
|
for d in self.finance_books:
|
||||||
|
if d.depreciation_start_date == self.available_for_use_date:
|
||||||
|
frappe.throw(_("Row #{}: Depreciation Posting Date should not be equal to Available for Use Date.").format(d.idx),
|
||||||
|
title=_("Incorrect Date"))
|
||||||
|
|
||||||
def set_missing_values(self):
|
def set_missing_values(self):
|
||||||
if not self.asset_category:
|
if not self.asset_category:
|
||||||
self.asset_category = frappe.get_cached_value("Item", self.item_code, "asset_category")
|
self.asset_category = frappe.get_cached_value("Item", self.item_code, "asset_category")
|
||||||
@@ -294,7 +299,7 @@ class Asset(AccountsController):
|
|||||||
if not row.depreciation_start_date:
|
if not row.depreciation_start_date:
|
||||||
if not self.available_for_use_date:
|
if not self.available_for_use_date:
|
||||||
frappe.throw(_("Row {0}: Depreciation Start Date is required").format(row.idx))
|
frappe.throw(_("Row {0}: Depreciation Start Date is required").format(row.idx))
|
||||||
row.depreciation_start_date = self.available_for_use_date
|
row.depreciation_start_date = get_last_day(self.available_for_use_date)
|
||||||
|
|
||||||
if not self.is_existing_asset:
|
if not self.is_existing_asset:
|
||||||
self.opening_accumulated_depreciation = 0
|
self.opening_accumulated_depreciation = 0
|
||||||
|
|||||||
@@ -371,19 +371,18 @@ class TestAsset(unittest.TestCase):
|
|||||||
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
|
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
|
||||||
asset = frappe.get_doc('Asset', asset_name)
|
asset = frappe.get_doc('Asset', asset_name)
|
||||||
asset.calculate_depreciation = 1
|
asset.calculate_depreciation = 1
|
||||||
asset.available_for_use_date = nowdate()
|
asset.available_for_use_date = '2020-01-01'
|
||||||
asset.purchase_date = nowdate()
|
asset.purchase_date = '2020-01-01'
|
||||||
asset.append("finance_books", {
|
asset.append("finance_books", {
|
||||||
"expected_value_after_useful_life": 10000,
|
"expected_value_after_useful_life": 10000,
|
||||||
"depreciation_method": "Straight Line",
|
"depreciation_method": "Straight Line",
|
||||||
"total_number_of_depreciations": 3,
|
"total_number_of_depreciations": 10,
|
||||||
"frequency_of_depreciation": 10,
|
"frequency_of_depreciation": 1
|
||||||
"depreciation_start_date": nowdate()
|
|
||||||
})
|
})
|
||||||
asset.insert()
|
asset.insert()
|
||||||
asset.submit()
|
asset.submit()
|
||||||
|
|
||||||
post_depreciation_entries(date=add_months(nowdate(), 10))
|
post_depreciation_entries(date=add_months('2020-01-01', 4))
|
||||||
|
|
||||||
scrap_asset(asset.name)
|
scrap_asset(asset.name)
|
||||||
|
|
||||||
@@ -392,9 +391,9 @@ class TestAsset(unittest.TestCase):
|
|||||||
self.assertTrue(asset.journal_entry_for_scrap)
|
self.assertTrue(asset.journal_entry_for_scrap)
|
||||||
|
|
||||||
expected_gle = (
|
expected_gle = (
|
||||||
("_Test Accumulated Depreciations - _TC", 30000.0, 0.0),
|
("_Test Accumulated Depreciations - _TC", 36000.0, 0.0),
|
||||||
("_Test Fixed Asset - _TC", 0.0, 100000.0),
|
("_Test Fixed Asset - _TC", 0.0, 100000.0),
|
||||||
("_Test Gain/Loss on Asset Disposal - _TC", 70000.0, 0.0)
|
("_Test Gain/Loss on Asset Disposal - _TC", 64000.0, 0.0)
|
||||||
)
|
)
|
||||||
|
|
||||||
gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
|
gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
|
||||||
@@ -466,8 +465,7 @@ class TestAsset(unittest.TestCase):
|
|||||||
"expected_value_after_useful_life": 10000,
|
"expected_value_after_useful_life": 10000,
|
||||||
"depreciation_method": "Straight Line",
|
"depreciation_method": "Straight Line",
|
||||||
"total_number_of_depreciations": 3,
|
"total_number_of_depreciations": 3,
|
||||||
"frequency_of_depreciation": 10,
|
"frequency_of_depreciation": 10
|
||||||
"depreciation_start_date": "2020-06-06"
|
|
||||||
})
|
})
|
||||||
asset.insert()
|
asset.insert()
|
||||||
accumulated_depreciation_after_full_schedule = \
|
accumulated_depreciation_after_full_schedule = \
|
||||||
|
|||||||
@@ -1,347 +1,99 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2018-05-08 14:44:37.095570",
|
"creation": "2018-05-08 14:44:37.095570",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"finance_book",
|
||||||
|
"depreciation_method",
|
||||||
|
"total_number_of_depreciations",
|
||||||
|
"column_break_5",
|
||||||
|
"frequency_of_depreciation",
|
||||||
|
"depreciation_start_date",
|
||||||
|
"expected_value_after_useful_life",
|
||||||
|
"value_after_depreciation",
|
||||||
|
"rate_of_depreciation"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "",
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "finance_book",
|
"fieldname": "finance_book",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Finance Book",
|
"label": "Finance Book",
|
||||||
"length": 0,
|
"options": "Finance Book"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Finance Book",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "depreciation_method",
|
"fieldname": "depreciation_method",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Depreciation Method",
|
"label": "Depreciation Method",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nStraight Line\nDouble Declining Balance\nWritten Down Value\nManual",
|
"options": "\nStraight Line\nDouble Declining Balance\nWritten Down Value\nManual",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "total_number_of_depreciations",
|
"fieldname": "total_number_of_depreciations",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Total Number of Depreciations",
|
"label": "Total Number of Depreciations",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"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": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "column_break_5",
|
"fieldname": "column_break_5",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "frequency_of_depreciation",
|
"fieldname": "frequency_of_depreciation",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Frequency of Depreciation (Months)",
|
"label": "Frequency of Depreciation (Months)",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"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": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "eval:parent.doctype == 'Asset'",
|
"depends_on": "eval:parent.doctype == 'Asset'",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "depreciation_start_date",
|
"fieldname": "depreciation_start_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"label": "Depreciation Posting Date",
|
||||||
"label": "Depreciation Start Date",
|
"reqd": 1
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"depends_on": "eval:parent.doctype == 'Asset'",
|
"depends_on": "eval:parent.doctype == 'Asset'",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "expected_value_after_useful_life",
|
"fieldname": "expected_value_after_useful_life",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"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": "Expected Value After Useful Life",
|
"label": "Expected Value After Useful Life",
|
||||||
"length": 0,
|
"options": "Company:company:default_currency"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Company:company:default_currency",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "value_after_depreciation",
|
"fieldname": "value_after_depreciation",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 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": "Value After Depreciation",
|
"label": "Value After Depreciation",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
"read_only": 1
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "eval:doc.depreciation_method == 'Written Down Value'",
|
"depends_on": "eval:doc.depreciation_method == 'Written Down Value'",
|
||||||
"description": "In Percentage",
|
"description": "In Percentage",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "rate_of_depreciation",
|
"fieldname": "rate_of_depreciation",
|
||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
"hidden": 0,
|
"label": "Rate of Depreciation"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Rate of Depreciation",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"index_web_pages_for_search": 1,
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"links": [],
|
||||||
"modified": "2019-04-09 19:45:14.523488",
|
"modified": "2020-09-16 12:11:30.631788",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Assets",
|
"module": "Assets",
|
||||||
"name": "Asset Finance Book",
|
"name": "Asset Finance Book",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"track_changes": 1
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
||||||
@@ -32,8 +32,7 @@ class TestAssetMovement(unittest.TestCase):
|
|||||||
"next_depreciation_date": "2020-12-31",
|
"next_depreciation_date": "2020-12-31",
|
||||||
"depreciation_method": "Straight Line",
|
"depreciation_method": "Straight Line",
|
||||||
"total_number_of_depreciations": 3,
|
"total_number_of_depreciations": 3,
|
||||||
"frequency_of_depreciation": 10,
|
"frequency_of_depreciation": 10
|
||||||
"depreciation_start_date": "2020-06-06"
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if asset.docstatus == 0:
|
if asset.docstatus == 0:
|
||||||
@@ -82,8 +81,7 @@ class TestAssetMovement(unittest.TestCase):
|
|||||||
"next_depreciation_date": "2020-12-31",
|
"next_depreciation_date": "2020-12-31",
|
||||||
"depreciation_method": "Straight Line",
|
"depreciation_method": "Straight Line",
|
||||||
"total_number_of_depreciations": 3,
|
"total_number_of_depreciations": 3,
|
||||||
"frequency_of_depreciation": 10,
|
"frequency_of_depreciation": 10
|
||||||
"depreciation_start_date": "2020-06-06"
|
|
||||||
})
|
})
|
||||||
if asset.docstatus == 0:
|
if asset.docstatus == 0:
|
||||||
asset.submit()
|
asset.submit()
|
||||||
|
|||||||
@@ -148,11 +148,11 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-03-12 15:43:53.862897",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order Item Supplied",
|
"name": "Purchase Order Item Supplied",
|
||||||
"owner": "dhanalekshmi@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC"
|
"sort_order": "DESC"
|
||||||
|
|||||||
@@ -188,11 +188,11 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-10 18:09:33.997618",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Receipt Item Supplied",
|
"name": "Purchase Receipt Item Supplied",
|
||||||
"owner": "wasim@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ class SellingController(StockController):
|
|||||||
party_details = _get_party_details(customer,
|
party_details = _get_party_details(customer,
|
||||||
ignore_permissions=self.flags.ignore_permissions,
|
ignore_permissions=self.flags.ignore_permissions,
|
||||||
doctype=self.doctype, company=self.company,
|
doctype=self.doctype, company=self.company,
|
||||||
|
posting_date=self.get('posting_date'),
|
||||||
fetch_payment_terms_template=fetch_payment_terms_template,
|
fetch_payment_terms_template=fetch_payment_terms_template,
|
||||||
party_address=self.customer_address, shipping_address=self.shipping_address_name)
|
party_address=self.customer_address, shipping_address=self.shipping_address_name)
|
||||||
if not self.meta.get_field("sales_team"):
|
if not self.meta.get_field("sales_team"):
|
||||||
|
|||||||
@@ -2,81 +2,90 @@
|
|||||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
import plaid
|
||||||
from frappe import _
|
import requests
|
||||||
from frappe.utils.password import get_decrypted_password
|
from plaid.errors import APIError, ItemError, InvalidRequestError
|
||||||
from plaid import Client
|
|
||||||
from plaid.errors import APIError, ItemError
|
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
import requests
|
from frappe import _
|
||||||
|
|
||||||
|
|
||||||
class PlaidConnector():
|
class PlaidConnector():
|
||||||
def __init__(self, access_token=None):
|
def __init__(self, access_token=None):
|
||||||
|
|
||||||
plaid_settings = frappe.get_single("Plaid Settings")
|
|
||||||
|
|
||||||
self.config = {
|
|
||||||
"plaid_client_id": plaid_settings.plaid_client_id,
|
|
||||||
"plaid_secret": get_decrypted_password("Plaid Settings", "Plaid Settings", 'plaid_secret'),
|
|
||||||
"plaid_public_key": plaid_settings.plaid_public_key,
|
|
||||||
"plaid_env": plaid_settings.plaid_env
|
|
||||||
}
|
|
||||||
|
|
||||||
self.client = Client(client_id=self.config.get("plaid_client_id"),
|
|
||||||
secret=self.config.get("plaid_secret"),
|
|
||||||
public_key=self.config.get("plaid_public_key"),
|
|
||||||
environment=self.config.get("plaid_env")
|
|
||||||
)
|
|
||||||
|
|
||||||
self.access_token = access_token
|
self.access_token = access_token
|
||||||
|
self.settings = frappe.get_single("Plaid Settings")
|
||||||
|
self.products = ["auth", "transactions"]
|
||||||
|
self.client_name = frappe.local.site
|
||||||
|
self.client = plaid.Client(
|
||||||
|
client_id=self.settings.plaid_client_id,
|
||||||
|
secret=self.settings.get_password("plaid_secret"),
|
||||||
|
environment=self.settings.plaid_env,
|
||||||
|
api_version="2019-05-29"
|
||||||
|
)
|
||||||
|
|
||||||
def get_access_token(self, public_token):
|
def get_access_token(self, public_token):
|
||||||
if public_token is None:
|
if public_token is None:
|
||||||
frappe.log_error(_("Public token is missing for this bank"), _("Plaid public token error"))
|
frappe.log_error(_("Public token is missing for this bank"), _("Plaid public token error"))
|
||||||
|
|
||||||
response = self.client.Item.public_token.exchange(public_token)
|
response = self.client.Item.public_token.exchange(public_token)
|
||||||
access_token = response['access_token']
|
access_token = response["access_token"]
|
||||||
|
|
||||||
return access_token
|
return access_token
|
||||||
|
|
||||||
|
def get_link_token(self):
|
||||||
|
token_request = {
|
||||||
|
"client_name": self.client_name,
|
||||||
|
"client_id": self.settings.plaid_client_id,
|
||||||
|
"secret": self.settings.plaid_secret,
|
||||||
|
"products": self.products,
|
||||||
|
# only allow Plaid-supported languages and countries (LAST: Sep-19-2020)
|
||||||
|
"language": frappe.local.lang if frappe.local.lang in ["en", "fr", "es", "nl"] else "en",
|
||||||
|
"country_codes": ["US", "CA", "FR", "IE", "NL", "ES", "GB"],
|
||||||
|
"user": {
|
||||||
|
"client_user_id": frappe.generate_hash(frappe.session.user, length=32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = self.client.LinkToken.create(token_request)
|
||||||
|
except InvalidRequestError:
|
||||||
|
frappe.log_error(frappe.get_traceback(), _("Plaid invalid request error"))
|
||||||
|
frappe.msgprint(_("Please check your Plaid client ID and secret values"))
|
||||||
|
except APIError as e:
|
||||||
|
frappe.log_error(frappe.get_traceback(), _("Plaid authentication error"))
|
||||||
|
frappe.throw(_(str(e)), title=_("Authentication Failed"))
|
||||||
|
else:
|
||||||
|
return response["link_token"]
|
||||||
|
|
||||||
def auth(self):
|
def auth(self):
|
||||||
try:
|
try:
|
||||||
self.client.Auth.get(self.access_token)
|
self.client.Auth.get(self.access_token)
|
||||||
print("Authentication successful.....")
|
|
||||||
except ItemError as e:
|
except ItemError as e:
|
||||||
if e.code == 'ITEM_LOGIN_REQUIRED':
|
if e.code == "ITEM_LOGIN_REQUIRED":
|
||||||
pass
|
|
||||||
else:
|
|
||||||
pass
|
pass
|
||||||
except APIError as e:
|
except APIError as e:
|
||||||
if e.code == 'PLANNED_MAINTENANCE':
|
if e.code == "PLANNED_MAINTENANCE":
|
||||||
pass
|
|
||||||
else:
|
|
||||||
pass
|
pass
|
||||||
except requests.Timeout:
|
except requests.Timeout:
|
||||||
pass
|
pass
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
|
||||||
frappe.log_error(frappe.get_traceback(), _("Plaid authentication error"))
|
frappe.log_error(frappe.get_traceback(), _("Plaid authentication error"))
|
||||||
frappe.msgprint({"title": _("Authentication Failed"), "message":e, "raise_exception":1, "indicator":'red'})
|
frappe.throw(_(str(e)), title=_("Authentication Failed"))
|
||||||
|
|
||||||
def get_transactions(self, start_date, end_date, account_id=None):
|
def get_transactions(self, start_date, end_date, account_id=None):
|
||||||
|
self.auth()
|
||||||
|
kwargs = dict(
|
||||||
|
access_token=self.access_token,
|
||||||
|
start_date=start_date,
|
||||||
|
end_date=end_date
|
||||||
|
)
|
||||||
|
if account_id:
|
||||||
|
kwargs.update(dict(account_ids=[account_id]))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.auth()
|
response = self.client.Transactions.get(**kwargs)
|
||||||
if account_id:
|
transactions = response["transactions"]
|
||||||
account_ids = [account_id]
|
while len(transactions) < response["total_transactions"]:
|
||||||
|
|
||||||
response = self.client.Transactions.get(self.access_token, start_date=start_date, end_date=end_date, account_ids=account_ids)
|
|
||||||
|
|
||||||
else:
|
|
||||||
response = self.client.Transactions.get(self.access_token, start_date=start_date, end_date=end_date)
|
|
||||||
|
|
||||||
transactions = response['transactions']
|
|
||||||
|
|
||||||
while len(transactions) < response['total_transactions']:
|
|
||||||
response = self.client.Transactions.get(self.access_token, start_date=start_date, end_date=end_date, offset=len(transactions))
|
response = self.client.Transactions.get(self.access_token, start_date=start_date, end_date=end_date, offset=len(transactions))
|
||||||
transactions.extend(response['transactions'])
|
transactions.extend(response["transactions"])
|
||||||
return transactions
|
return transactions
|
||||||
except Exception:
|
except Exception:
|
||||||
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
|
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
frappe.provide("erpnext.integrations");
|
frappe.provide("erpnext.integrations");
|
||||||
|
|
||||||
frappe.ui.form.on('Plaid Settings', {
|
frappe.ui.form.on('Plaid Settings', {
|
||||||
enabled: function(frm) {
|
enabled: function (frm) {
|
||||||
frm.toggle_reqd('plaid_client_id', frm.doc.enabled);
|
frm.toggle_reqd('plaid_client_id', frm.doc.enabled);
|
||||||
frm.toggle_reqd('plaid_secret', frm.doc.enabled);
|
frm.toggle_reqd('plaid_secret', frm.doc.enabled);
|
||||||
frm.toggle_reqd('plaid_public_key', frm.doc.enabled);
|
|
||||||
frm.toggle_reqd('plaid_env', frm.doc.enabled);
|
frm.toggle_reqd('plaid_env', frm.doc.enabled);
|
||||||
},
|
},
|
||||||
refresh: function(frm) {
|
|
||||||
if(frm.doc.enabled) {
|
refresh: function (frm) {
|
||||||
|
if (frm.doc.enabled) {
|
||||||
frm.add_custom_button('Link a new bank account', () => {
|
frm.add_custom_button('Link a new bank account', () => {
|
||||||
new erpnext.integrations.plaidLink(frm);
|
new erpnext.integrations.plaidLink(frm);
|
||||||
});
|
});
|
||||||
@@ -22,17 +22,16 @@ frappe.ui.form.on('Plaid Settings', {
|
|||||||
erpnext.integrations.plaidLink = class plaidLink {
|
erpnext.integrations.plaidLink = class plaidLink {
|
||||||
constructor(parent) {
|
constructor(parent) {
|
||||||
this.frm = parent;
|
this.frm = parent;
|
||||||
this.product = ["transactions", "auth"];
|
|
||||||
this.plaidUrl = 'https://cdn.plaid.com/link/v2/stable/link-initialize.js';
|
this.plaidUrl = 'https://cdn.plaid.com/link/v2/stable/link-initialize.js';
|
||||||
this.init_config();
|
this.init_config();
|
||||||
}
|
}
|
||||||
|
|
||||||
init_config() {
|
async init_config() {
|
||||||
const me = this;
|
this.product = ["auth", "transactions"];
|
||||||
me.plaid_env = me.frm.doc.plaid_env;
|
this.plaid_env = this.frm.doc.plaid_env;
|
||||||
me.plaid_public_key = me.frm.doc.plaid_public_key;
|
this.client_name = frappe.boot.sitename;
|
||||||
me.client_name = frappe.boot.sitename;
|
this.token = await this.frm.call("get_link_token").then(resp => resp.message);
|
||||||
me.init_plaid();
|
this.init_plaid();
|
||||||
}
|
}
|
||||||
|
|
||||||
init_plaid() {
|
init_plaid() {
|
||||||
@@ -69,17 +68,17 @@ erpnext.integrations.plaidLink = class plaidLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onScriptLoaded(me) {
|
onScriptLoaded(me) {
|
||||||
me.linkHandler = window.Plaid.create({
|
me.linkHandler = Plaid.create({
|
||||||
clientName: me.client_name,
|
clientName: me.client_name,
|
||||||
|
product: me.product,
|
||||||
env: me.plaid_env,
|
env: me.plaid_env,
|
||||||
key: me.plaid_public_key,
|
token: me.token,
|
||||||
onSuccess: me.plaid_success,
|
onSuccess: me.plaid_success
|
||||||
product: me.product
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onScriptError(error) {
|
onScriptError(error) {
|
||||||
frappe.msgprint('There was an issue loading the link-initialize.js script');
|
frappe.msgprint("There was an issue connecting to Plaid's authentication server");
|
||||||
frappe.msgprint(error);
|
frappe.msgprint(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,21 +86,25 @@ erpnext.integrations.plaidLink = class plaidLink {
|
|||||||
const me = this;
|
const me = this;
|
||||||
|
|
||||||
frappe.prompt({
|
frappe.prompt({
|
||||||
fieldtype:"Link",
|
fieldtype: "Link",
|
||||||
options: "Company",
|
options: "Company",
|
||||||
label:__("Company"),
|
label: __("Company"),
|
||||||
fieldname:"company",
|
fieldname: "company",
|
||||||
reqd:1
|
reqd: 1
|
||||||
}, (data) => {
|
}, (data) => {
|
||||||
me.company = data.company;
|
me.company = data.company;
|
||||||
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.add_institution', {token: token, response: response})
|
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.add_institution', {
|
||||||
.then((result) => {
|
token: token,
|
||||||
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.add_bank_accounts', {response: response,
|
response: response
|
||||||
bank: result, company: me.company});
|
}).then((result) => {
|
||||||
})
|
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.add_bank_accounts', {
|
||||||
.then(() => {
|
response: response,
|
||||||
frappe.show_alert({message:__("Bank accounts added"), indicator:'green'});
|
bank: result,
|
||||||
|
company: me.company
|
||||||
});
|
});
|
||||||
|
}).then(() => {
|
||||||
|
frappe.show_alert({ message: __("Bank accounts added"), indicator: 'green' });
|
||||||
|
});
|
||||||
}, __("Select a company"), __("Continue"));
|
}, __("Select a company"), __("Continue"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
|
||||||
"creation": "2018-10-25 10:02:48.656165",
|
"creation": "2018-10-25 10:02:48.656165",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@@ -12,7 +11,6 @@
|
|||||||
"plaid_client_id",
|
"plaid_client_id",
|
||||||
"plaid_secret",
|
"plaid_secret",
|
||||||
"column_break_7",
|
"column_break_7",
|
||||||
"plaid_public_key",
|
|
||||||
"plaid_env"
|
"plaid_env"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
@@ -41,12 +39,6 @@
|
|||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Plaid Secret"
|
"label": "Plaid Secret"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "plaid_public_key",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Plaid Public Key"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "plaid_env",
|
"fieldname": "plaid_env",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
@@ -69,8 +61,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"modified": "2020-09-12 02:31:44.542385",
|
||||||
"modified": "2020-02-07 15:21:11.616231",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "ERPNext Integrations",
|
"module": "ERPNext Integrations",
|
||||||
"name": "Plaid Settings",
|
"name": "Plaid Settings",
|
||||||
|
|||||||
@@ -2,30 +2,36 @@
|
|||||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
import json
|
import json
|
||||||
from frappe import _
|
|
||||||
from frappe.model.document import Document
|
import frappe
|
||||||
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
|
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
|
||||||
from erpnext.erpnext_integrations.doctype.plaid_settings.plaid_connector import PlaidConnector
|
from erpnext.erpnext_integrations.doctype.plaid_settings.plaid_connector import PlaidConnector
|
||||||
from frappe.utils import getdate, formatdate, today, add_months
|
from frappe import _
|
||||||
from frappe.desk.doctype.tag.tag import add_tag
|
from frappe.desk.doctype.tag.tag import add_tag
|
||||||
|
from frappe.model.document import Document
|
||||||
|
from frappe.utils import add_months, formatdate, getdate, today
|
||||||
|
|
||||||
|
|
||||||
class PlaidSettings(Document):
|
class PlaidSettings(Document):
|
||||||
pass
|
@staticmethod
|
||||||
|
def get_link_token():
|
||||||
|
plaid = PlaidConnector()
|
||||||
|
return plaid.get_link_token()
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def plaid_configuration():
|
def get_plaid_configuration():
|
||||||
if frappe.db.get_single_value("Plaid Settings", "enabled"):
|
if frappe.db.get_single_value("Plaid Settings", "enabled"):
|
||||||
plaid_settings = frappe.get_single("Plaid Settings")
|
plaid_settings = frappe.get_single("Plaid Settings")
|
||||||
return {
|
return {
|
||||||
"plaid_public_key": plaid_settings.plaid_public_key,
|
|
||||||
"plaid_env": plaid_settings.plaid_env,
|
"plaid_env": plaid_settings.plaid_env,
|
||||||
|
"link_token": plaid_settings.get_link_token(),
|
||||||
"client_name": frappe.local.site
|
"client_name": frappe.local.site
|
||||||
}
|
}
|
||||||
else:
|
|
||||||
return "disabled"
|
return "disabled"
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def add_institution(token, response):
|
def add_institution(token, response):
|
||||||
@@ -33,6 +39,7 @@ def add_institution(token, response):
|
|||||||
|
|
||||||
plaid = PlaidConnector()
|
plaid = PlaidConnector()
|
||||||
access_token = plaid.get_access_token(token)
|
access_token = plaid.get_access_token(token)
|
||||||
|
bank = None
|
||||||
|
|
||||||
if not frappe.db.exists("Bank", response["institution"]["name"]):
|
if not frappe.db.exists("Bank", response["institution"]["name"]):
|
||||||
try:
|
try:
|
||||||
@@ -44,7 +51,6 @@ def add_institution(token, response):
|
|||||||
bank.insert()
|
bank.insert()
|
||||||
except Exception:
|
except Exception:
|
||||||
frappe.throw(frappe.get_traceback())
|
frappe.throw(frappe.get_traceback())
|
||||||
|
|
||||||
else:
|
else:
|
||||||
bank = frappe.get_doc("Bank", response["institution"]["name"])
|
bank = frappe.get_doc("Bank", response["institution"]["name"])
|
||||||
bank.plaid_access_token = access_token
|
bank.plaid_access_token = access_token
|
||||||
@@ -52,6 +58,7 @@ def add_institution(token, response):
|
|||||||
|
|
||||||
return bank
|
return bank
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def add_bank_accounts(response, bank, company):
|
def add_bank_accounts(response, bank, company):
|
||||||
try:
|
try:
|
||||||
@@ -92,9 +99,8 @@ def add_bank_accounts(response, bank, company):
|
|||||||
new_account.insert()
|
new_account.insert()
|
||||||
|
|
||||||
result.append(new_account.name)
|
result.append(new_account.name)
|
||||||
|
|
||||||
except frappe.UniqueValidationError:
|
except frappe.UniqueValidationError:
|
||||||
frappe.msgprint(_("Bank account {0} already exists and could not be created again").format(new_account.account_name))
|
frappe.msgprint(_("Bank account {0} already exists and could not be created again").format(account["name"]))
|
||||||
except Exception:
|
except Exception:
|
||||||
frappe.throw(frappe.get_traceback())
|
frappe.throw(frappe.get_traceback())
|
||||||
|
|
||||||
@@ -103,6 +109,7 @@ def add_bank_accounts(response, bank, company):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def add_account_type(account_type):
|
def add_account_type(account_type):
|
||||||
try:
|
try:
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
@@ -122,10 +129,11 @@ def add_account_subtype(account_subtype):
|
|||||||
except Exception:
|
except Exception:
|
||||||
frappe.throw(frappe.get_traceback())
|
frappe.throw(frappe.get_traceback())
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def sync_transactions(bank, bank_account):
|
def sync_transactions(bank, bank_account):
|
||||||
'''Sync transactions based on the last integration date as the start date, after the sync is completed
|
"""Sync transactions based on the last integration date as the start date, after sync is completed
|
||||||
add the transaction date of the oldest transaction as the last integration date'''
|
add the transaction date of the oldest transaction as the last integration date."""
|
||||||
last_transaction_date = frappe.db.get_value("Bank Account", bank_account, "last_integration_date")
|
last_transaction_date = frappe.db.get_value("Bank Account", bank_account, "last_integration_date")
|
||||||
if last_transaction_date:
|
if last_transaction_date:
|
||||||
start_date = formatdate(last_transaction_date, "YYYY-MM-dd")
|
start_date = formatdate(last_transaction_date, "YYYY-MM-dd")
|
||||||
@@ -147,10 +155,10 @@ def sync_transactions(bank, bank_account):
|
|||||||
len(result), bank_account, start_date, end_date))
|
len(result), bank_account, start_date, end_date))
|
||||||
|
|
||||||
frappe.db.set_value("Bank Account", bank_account, "last_integration_date", last_transaction_date)
|
frappe.db.set_value("Bank Account", bank_account, "last_integration_date", last_transaction_date)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
|
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
|
||||||
|
|
||||||
|
|
||||||
def get_transactions(bank, bank_account=None, start_date=None, end_date=None):
|
def get_transactions(bank, bank_account=None, start_date=None, end_date=None):
|
||||||
access_token = None
|
access_token = None
|
||||||
|
|
||||||
@@ -168,6 +176,7 @@ def get_transactions(bank, bank_account=None, start_date=None, end_date=None):
|
|||||||
|
|
||||||
return transactions
|
return transactions
|
||||||
|
|
||||||
|
|
||||||
def new_bank_transaction(transaction):
|
def new_bank_transaction(transaction):
|
||||||
result = []
|
result = []
|
||||||
|
|
||||||
@@ -182,8 +191,8 @@ def new_bank_transaction(transaction):
|
|||||||
|
|
||||||
status = "Pending" if transaction["pending"] == "True" else "Settled"
|
status = "Pending" if transaction["pending"] == "True" else "Settled"
|
||||||
|
|
||||||
|
tags = []
|
||||||
try:
|
try:
|
||||||
tags = []
|
|
||||||
tags += transaction["category"]
|
tags += transaction["category"]
|
||||||
tags += ["Plaid Cat. {}".format(transaction["category_id"])]
|
tags += ["Plaid Cat. {}".format(transaction["category_id"])]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@@ -216,6 +225,7 @@ def new_bank_transaction(transaction):
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def automatic_synchronization():
|
def automatic_synchronization():
|
||||||
settings = frappe.get_doc("Plaid Settings", "Plaid Settings")
|
settings = frappe.get_doc("Plaid Settings", "Plaid Settings")
|
||||||
|
|
||||||
@@ -223,4 +233,8 @@ def automatic_synchronization():
|
|||||||
plaid_accounts = frappe.get_all("Bank Account", filters={"integration_id": ["!=", ""]}, fields=["name", "bank"])
|
plaid_accounts = frappe.get_all("Bank Account", filters={"integration_id": ["!=", ""]}, fields=["name", "bank"])
|
||||||
|
|
||||||
for plaid_account in plaid_accounts:
|
for plaid_account in plaid_accounts:
|
||||||
frappe.enqueue("erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.sync_transactions", bank=plaid_account.bank, bank_account=plaid_account.name)
|
frappe.enqueue(
|
||||||
|
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.sync_transactions",
|
||||||
|
bank=plaid_account.bank,
|
||||||
|
bank_account=plaid_account.name
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# See license.txt
|
# See license.txt
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
import frappe
|
|
||||||
from erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings import plaid_configuration, add_account_type, add_account_subtype, new_bank_transaction, add_bank_accounts
|
|
||||||
import json
|
import json
|
||||||
from frappe.utils.response import json_handler
|
import unittest
|
||||||
|
|
||||||
|
import frappe
|
||||||
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
|
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
|
||||||
|
from erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings import (
|
||||||
|
add_account_subtype, add_account_type, add_bank_accounts,
|
||||||
|
new_bank_transaction, get_plaid_configuration)
|
||||||
|
from frappe.utils.response import json_handler
|
||||||
|
|
||||||
|
|
||||||
class TestPlaidSettings(unittest.TestCase):
|
class TestPlaidSettings(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -31,7 +34,7 @@ class TestPlaidSettings(unittest.TestCase):
|
|||||||
|
|
||||||
def test_plaid_disabled(self):
|
def test_plaid_disabled(self):
|
||||||
frappe.db.set_value("Plaid Settings", None, "enabled", 0)
|
frappe.db.set_value("Plaid Settings", None, "enabled", 0)
|
||||||
self.assertTrue(plaid_configuration() == "disabled")
|
self.assertTrue(get_plaid_configuration() == "disabled")
|
||||||
|
|
||||||
def test_add_account_type(self):
|
def test_add_account_type(self):
|
||||||
add_account_type("brokerage")
|
add_account_type("brokerage")
|
||||||
@@ -64,7 +67,7 @@ class TestPlaidSettings(unittest.TestCase):
|
|||||||
'mask': '0000',
|
'mask': '0000',
|
||||||
'id': '6GbM6RRQgdfy3lAqGz4JUnpmR948WZFg8DjQK',
|
'id': '6GbM6RRQgdfy3lAqGz4JUnpmR948WZFg8DjQK',
|
||||||
'name': 'Plaid Checking'
|
'name': 'Plaid Checking'
|
||||||
}],
|
}],
|
||||||
'institution': {
|
'institution': {
|
||||||
'institution_id': 'ins_6',
|
'institution_id': 'ins_6',
|
||||||
'name': 'Citi'
|
'name': 'Citi'
|
||||||
@@ -100,7 +103,7 @@ class TestPlaidSettings(unittest.TestCase):
|
|||||||
'mask': '0000',
|
'mask': '0000',
|
||||||
'id': '6GbM6RRQgdfy3lAqGz4JUnpmR948WZFg8DjQK',
|
'id': '6GbM6RRQgdfy3lAqGz4JUnpmR948WZFg8DjQK',
|
||||||
'name': 'Plaid Checking'
|
'name': 'Plaid Checking'
|
||||||
}],
|
}],
|
||||||
'institution': {
|
'institution': {
|
||||||
'institution_id': 'ins_6',
|
'institution_id': 'ins_6',
|
||||||
'name': 'Citi'
|
'name': 'Citi'
|
||||||
|
|||||||
@@ -258,8 +258,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"modified": "2020-05-28 12:32:11.384757",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "umair@erpnext.com",
|
"modified_by": "Administrator",
|
||||||
"module": "ERPNext Integrations",
|
"module": "ERPNext Integrations",
|
||||||
"name": "Shopify Settings",
|
"name": "Shopify Settings",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
|||||||
@@ -117,12 +117,12 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-05-08 13:45:57.226530",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Healthcare",
|
"module": "Healthcare",
|
||||||
"name": "Healthcare Schedule Time Slot",
|
"name": "Healthcare Schedule Time Slot",
|
||||||
"name_case": "",
|
"name_case": "",
|
||||||
"owner": "rmehta@gmail.com",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
|||||||
@@ -44,11 +44,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-01-31 12:21:45.975488",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Healthcare",
|
"module": "Healthcare",
|
||||||
"name": "Practitioner Schedule",
|
"name": "Practitioner Schedule",
|
||||||
"owner": "rmehta@gmail.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"create": 1,
|
"create": 1,
|
||||||
|
|||||||
@@ -696,11 +696,11 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2019-01-30 11:28:08.401459",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Appraisal",
|
"name": "Appraisal",
|
||||||
"owner": "ashwini@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
|
|||||||
@@ -207,11 +207,11 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-07-11 03:27:57.897071",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Appraisal Goal",
|
"name": "Appraisal Goal",
|
||||||
"owner": "ashwini@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 0,
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
|||||||
@@ -113,11 +113,11 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-12-13 12:37:56.937023",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Appraisal Template",
|
"name": "Appraisal Template",
|
||||||
"owner": "ashwini@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
|
|||||||
@@ -78,11 +78,11 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-07-11 03:27:57.979215",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Appraisal Template Goal",
|
"name": "Appraisal Template Goal",
|
||||||
"owner": "ashwini@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 0,
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
|||||||
@@ -205,11 +205,11 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-05-29 13:51:37.177231",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Attendance",
|
"name": "Attendance",
|
||||||
"owner": "ashwini@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"cancel": 1,
|
"cancel": 1,
|
||||||
|
|||||||
@@ -371,12 +371,12 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-06-15 12:43:04.099803",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Expense Claim",
|
"name": "Expense Claim",
|
||||||
"name_case": "Title Case",
|
"name_case": "Title Case",
|
||||||
"owner": "harshada@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 1,
|
"amend": 1,
|
||||||
|
|||||||
@@ -120,11 +120,11 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-05-11 18:54:35.601592",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Expense Claim Detail",
|
"name": "Expense Claim Detail",
|
||||||
"owner": "harshada@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC"
|
"sort_order": "DESC"
|
||||||
|
|||||||
@@ -48,11 +48,11 @@
|
|||||||
"icon": "fa fa-flag",
|
"icon": "fa fa-flag",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2019-12-11 13:38:59.534034",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Expense Claim Type",
|
"name": "Expense Claim Type",
|
||||||
"owner": "harshada@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"create": 1,
|
"create": 1,
|
||||||
|
|||||||
@@ -229,11 +229,11 @@
|
|||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 1,
|
"max_attachments": 1,
|
||||||
"modified": "2017-11-14 12:51:34.980103",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Upload Attendance",
|
"name": "Upload Attendance",
|
||||||
"owner": "harshada@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
|
|||||||
@@ -40,8 +40,8 @@
|
|||||||
"mapping_name": "Company to Hub Company",
|
"mapping_name": "Company to Hub Company",
|
||||||
"mapping_type": "Push",
|
"mapping_type": "Push",
|
||||||
"migration_id_field": "hub_sync_id",
|
"migration_id_field": "hub_sync_id",
|
||||||
"modified": "2018-02-14 15:57:05.571142",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "achilles@erpnext.com",
|
"modified_by": "Administrator",
|
||||||
"name": "Company to Hub Company",
|
"name": "Company to Hub Company",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"page_length": 10,
|
"page_length": 10,
|
||||||
|
|||||||
@@ -21,10 +21,10 @@
|
|||||||
"mapping_name": "Hub Message to Lead",
|
"mapping_name": "Hub Message to Lead",
|
||||||
"mapping_type": "Pull",
|
"mapping_type": "Pull",
|
||||||
"migration_id_field": "hub_sync_id",
|
"migration_id_field": "hub_sync_id",
|
||||||
"modified": "2018-02-14 15:57:05.606597",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "achilles@erpnext.com",
|
"modified_by": "Administrator",
|
||||||
"name": "Hub Message to Lead",
|
"name": "Hub Message to Lead",
|
||||||
"owner": "frappetest@gmail.com",
|
"owner": "Administrator",
|
||||||
"page_length": 10,
|
"page_length": 10,
|
||||||
"remote_objectname": "Hub Message",
|
"remote_objectname": "Hub Message",
|
||||||
"remote_primary_key": "name"
|
"remote_primary_key": "name"
|
||||||
|
|||||||
@@ -121,8 +121,8 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-09-01 13:56:07.816894",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "netchamp@rawcoderz.com",
|
"modified_by": "Administrator",
|
||||||
"module": "Hub Node",
|
"module": "Hub Node",
|
||||||
"name": "Hub User",
|
"name": "Hub User",
|
||||||
"name_case": "",
|
"name_case": "",
|
||||||
|
|||||||
@@ -54,12 +54,12 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-03-06 04:41:17.916243",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Hub Node",
|
"module": "Hub Node",
|
||||||
"name": "Hub Users",
|
"name": "Hub Users",
|
||||||
"name_case": "",
|
"name_case": "",
|
||||||
"owner": "test1@example.com",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
|||||||
@@ -352,12 +352,12 @@
|
|||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2019-02-01 14:21:16.729848",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Hub Node",
|
"module": "Hub Node",
|
||||||
"name": "Marketplace Settings",
|
"name": "Marketplace Settings",
|
||||||
"name_case": "",
|
"name_case": "",
|
||||||
"owner": "netchamp@rawcoderz.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
|
|||||||
@@ -813,7 +813,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-08-21 14:44:33.670332",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Maintenance",
|
"module": "Maintenance",
|
||||||
"name": "Maintenance Schedule",
|
"name": "Maintenance Schedule",
|
||||||
|
|||||||
@@ -1001,11 +1001,11 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2020-07-15 14:44:44.911402",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Maintenance",
|
"module": "Maintenance",
|
||||||
"name": "Maintenance Visit",
|
"name": "Maintenance Visit",
|
||||||
"owner": "ashwini@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 1,
|
"amend": 1,
|
||||||
|
|||||||
@@ -125,11 +125,11 @@
|
|||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-10-03 14:55:52.786805",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Maintenance",
|
"module": "Maintenance",
|
||||||
"name": "Maintenance Visit Purpose",
|
"name": "Maintenance Visit Purpose",
|
||||||
"owner": "ashwini@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
|||||||
@@ -90,9 +90,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "currency",
|
"fieldname": "currency",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Link",
|
||||||
"label": "Currency",
|
"label": "Currency",
|
||||||
"options": "USD\nINR"
|
"options": "Currency"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "amount",
|
"fieldname": "amount",
|
||||||
@@ -126,7 +126,7 @@
|
|||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-07-31 13:57:02.328995",
|
"modified": "2020-09-19 14:28:11.532696",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Non Profit",
|
"module": "Non Profit",
|
||||||
"name": "Membership",
|
"name": "Membership",
|
||||||
|
|||||||
@@ -4,17 +4,16 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
frappe.reload_doc("erpnext_integrations", "doctype", "plaid_settings")
|
frappe.reload_doc("erpnext_integrations", "doctype", "plaid_settings")
|
||||||
plaid_settings = frappe.get_single("Plaid Settings")
|
plaid_settings = frappe.get_single("Plaid Settings")
|
||||||
if plaid_settings.enabled:
|
if plaid_settings.enabled:
|
||||||
if not (frappe.conf.plaid_client_id and frappe.conf.plaid_env \
|
if not (frappe.conf.plaid_client_id and frappe.conf.plaid_env and frappe.conf.plaid_secret):
|
||||||
and frappe.conf.plaid_public_key and frappe.conf.plaid_secret):
|
|
||||||
plaid_settings.enabled = 0
|
plaid_settings.enabled = 0
|
||||||
else:
|
else:
|
||||||
plaid_settings.update({
|
plaid_settings.update({
|
||||||
"plaid_client_id": frappe.conf.plaid_client_id,
|
"plaid_client_id": frappe.conf.plaid_client_id,
|
||||||
"plaid_public_key": frappe.conf.plaid_public_key,
|
|
||||||
"plaid_env": frappe.conf.plaid_env,
|
"plaid_env": frappe.conf.plaid_env,
|
||||||
"plaid_secret": frappe.conf.plaid_secret
|
"plaid_secret": frappe.conf.plaid_secret
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -48,8 +48,8 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-10-26 17:37:25.638190",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "rohitw1991@gmail.com",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Dependent Task",
|
"name": "Dependent Task",
|
||||||
"name_case": "",
|
"name_case": "",
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ $.extend(frappe.breadcrumbs.preferred, {
|
|||||||
"Territory": "Selling",
|
"Territory": "Selling",
|
||||||
"Sales Person": "Selling",
|
"Sales Person": "Selling",
|
||||||
"Sales Partner": "Selling",
|
"Sales Partner": "Selling",
|
||||||
"Brand": "Stock"
|
"Brand": "Stock",
|
||||||
|
"Maintenance Schedule": "Support",
|
||||||
|
"Maintenance Visit": "Support"
|
||||||
});
|
});
|
||||||
|
|
||||||
$.extend(frappe.breadcrumbs.module_map, {
|
$.extend(frappe.breadcrumbs.module_map, {
|
||||||
|
|||||||
@@ -224,6 +224,10 @@ erpnext.utils.set_taxes = function(frm, triggered_from_field) {
|
|||||||
party = frm.doc.party_name;
|
party = frm.doc.party_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!frm.doc.company) {
|
||||||
|
frappe.throw(__("Kindly select the company first"));
|
||||||
|
}
|
||||||
|
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.accounts.party.set_taxes",
|
method: "erpnext.accounts.party.set_taxes",
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -49,11 +49,11 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-07-25 05:24:25.881361",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Industry Type",
|
"name": "Industry Type",
|
||||||
"owner": "harshada@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
|
|||||||
@@ -238,8 +238,8 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-10-18 14:23:06.538568",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "tundebabzy@gmail.com",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Product Bundle",
|
"name": "Product Bundle",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
|||||||
@@ -70,13 +70,23 @@ erpnext.PointOfSale.Payment = class {
|
|||||||
this.$invoice_fields.append(
|
this.$invoice_fields.append(
|
||||||
`<div class="invoice_detail_field ${df.fieldname}-field" data-fieldname="${df.fieldname}"></div>`
|
`<div class="invoice_detail_field ${df.fieldname}-field" data-fieldname="${df.fieldname}"></div>`
|
||||||
);
|
);
|
||||||
|
let df_events = {
|
||||||
|
onchange: function() { frm.set_value(this.df.fieldname, this.value); }
|
||||||
|
}
|
||||||
|
if (df.fieldtype == "Button") {
|
||||||
|
df_events = {
|
||||||
|
click: function() {
|
||||||
|
if (frm.script_manager.has_handlers(df.fieldname, frm.doc.doctype)) {
|
||||||
|
frm.script_manager.trigger(df.fieldname, frm.doc.doctype, frm.doc.docname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this[`${df.fieldname}_field`] = frappe.ui.form.make_control({
|
this[`${df.fieldname}_field`] = frappe.ui.form.make_control({
|
||||||
df: {
|
df: {
|
||||||
...df,
|
...df,
|
||||||
onchange: function() {
|
...df_events
|
||||||
frm.set_value(this.df.fieldname, this.value);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
parent: this.$invoice_fields.find(`.${df.fieldname}-field`),
|
parent: this.$invoice_fields.find(`.${df.fieldname}-field`),
|
||||||
render_input: true,
|
render_input: true,
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ def get_conditions(filters):
|
|||||||
conditions += "AND so.transaction_date <= '%s'" %filters.to_date
|
conditions += "AND so.transaction_date <= '%s'" %filters.to_date
|
||||||
|
|
||||||
if filters.get("item_code"):
|
if filters.get("item_code"):
|
||||||
conditions += "AND so_item.item_code = '%s'" %frappe.db.escape(filters.item_code)
|
conditions += "AND so_item.item_code = %s" %frappe.db.escape(filters.item_code)
|
||||||
|
|
||||||
if filters.get("customer"):
|
if filters.get("customer"):
|
||||||
conditions += "AND so.customer = %s" %frappe.db.escape(filters.customer)
|
conditions += "AND so.customer = %s" %frappe.db.escape(filters.customer)
|
||||||
|
|||||||
@@ -166,11 +166,11 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"max_attachments": 5,
|
"max_attachments": 5,
|
||||||
"modified": "2019-10-03 22:38:45.104056",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Batch",
|
"name": "Batch",
|
||||||
"owner": "harshada@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"create": 1,
|
"create": 1,
|
||||||
|
|||||||
@@ -133,11 +133,11 @@
|
|||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-11-12 15:41:21.053462",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Landed Cost Item",
|
"name": "Landed Cost Item",
|
||||||
"owner": "wasim@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC"
|
"sort_order": "DESC"
|
||||||
|
|||||||
@@ -173,11 +173,11 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-07-20 10:49:34.228751",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Landed Cost Purchase Receipt",
|
"name": "Landed Cost Purchase Receipt",
|
||||||
"owner": "wasim@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 0,
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
|
|||||||
@@ -494,8 +494,7 @@ class TestPurchaseReceipt(unittest.TestCase):
|
|||||||
"expected_value_after_useful_life": 10,
|
"expected_value_after_useful_life": 10,
|
||||||
"depreciation_method": "Straight Line",
|
"depreciation_method": "Straight Line",
|
||||||
"total_number_of_depreciations": 3,
|
"total_number_of_depreciations": 3,
|
||||||
"frequency_of_depreciation": 1,
|
"frequency_of_depreciation": 1
|
||||||
"depreciation_start_date": frappe.utils.nowdate()
|
|
||||||
})
|
})
|
||||||
asset.submit()
|
asset.submit()
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,24 @@ frappe.ui.form.on('Stock Entry', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frm.set_query('source_warehouse_address', function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
link_doctype: 'Warehouse',
|
||||||
|
link_name: frm.doc.from_warehouse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.set_query('target_warehouse_address', function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
link_doctype: 'Warehouse',
|
||||||
|
link_name: frm.doc.to_warehouse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
frappe.db.get_value('Stock Settings', {name: 'Stock Settings'}, 'sample_retention_warehouse', (r) => {
|
frappe.db.get_value('Stock Settings', {name: 'Stock Settings'}, 'sample_retention_warehouse', (r) => {
|
||||||
if (r.sample_retention_warehouse) {
|
if (r.sample_retention_warehouse) {
|
||||||
var filters = [
|
var filters = [
|
||||||
|
|||||||
@@ -361,11 +361,11 @@
|
|||||||
],
|
],
|
||||||
"icon": "fa fa-bug",
|
"icon": "fa fa-bug",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2019-05-24 10:56:30.626200",
|
"modified": "2020-09-18 17:26:09.703215",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Support",
|
"module": "Support",
|
||||||
"name": "Warranty Claim",
|
"name": "Warranty Claim",
|
||||||
"owner": "harshada@webnotestech.com",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"create": 1,
|
"create": 1,
|
||||||
|
|||||||
@@ -11,8 +11,39 @@ def get_level():
|
|||||||
activation_level = 0
|
activation_level = 0
|
||||||
sales_data = []
|
sales_data = []
|
||||||
min_count = 0
|
min_count = 0
|
||||||
doctypes = {"Item": 5, "Customer": 5, "Sales Order": 2, "Sales Invoice": 2, "Purchase Order": 2, "Employee": 3, "Lead": 3, "Quotation": 3,
|
doctypes = {
|
||||||
"Payment Entry": 2, "User": 5, "Student": 5, "Instructor": 5, "BOM": 3, "Journal Entry": 3, "Stock Entry": 3}
|
"Asset": 5,
|
||||||
|
"BOM": 3,
|
||||||
|
"Customer": 5,
|
||||||
|
"Delivery Note": 5,
|
||||||
|
"Employee": 3,
|
||||||
|
"Instructor": 5,
|
||||||
|
"Instructor": 5,
|
||||||
|
"Issue": 5,
|
||||||
|
"Item": 5,
|
||||||
|
"Journal Entry": 3,
|
||||||
|
"Lead": 3,
|
||||||
|
"Leave Application": 5,
|
||||||
|
"Material Request": 5,
|
||||||
|
"Opportunity": 5,
|
||||||
|
"Payment Entry": 2,
|
||||||
|
"Project": 5,
|
||||||
|
"Purchase Order": 2,
|
||||||
|
"Purchase Invoice": 5,
|
||||||
|
"Purchase Receipt": 5,
|
||||||
|
"Quotation": 3,
|
||||||
|
"Salary Slip": 5,
|
||||||
|
"Salary Structure": 5,
|
||||||
|
"Sales Order": 2,
|
||||||
|
"Sales Invoice": 2,
|
||||||
|
"Stock Entry": 3,
|
||||||
|
"Student": 5,
|
||||||
|
"Supplier": 5,
|
||||||
|
"Task": 5,
|
||||||
|
"User": 5,
|
||||||
|
"Work Order": 5
|
||||||
|
}
|
||||||
|
|
||||||
for doctype, min_count in iteritems(doctypes):
|
for doctype, min_count in iteritems(doctypes):
|
||||||
count = frappe.db.count(doctype)
|
count = frappe.db.count(doctype)
|
||||||
if count > min_count:
|
if count > min_count:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ frappe
|
|||||||
gocardless-pro==1.11.0
|
gocardless-pro==1.11.0
|
||||||
googlemaps==3.1.1
|
googlemaps==3.1.1
|
||||||
pandas==1.0.5
|
pandas==1.0.5
|
||||||
plaid-python==3.4.0
|
plaid-python==6.0.0
|
||||||
pycountry==19.8.18
|
pycountry==19.8.18
|
||||||
PyGithub==1.44.1
|
PyGithub==1.44.1
|
||||||
python-stdnum==1.12
|
python-stdnum==1.12
|
||||||
|
|||||||
Reference in New Issue
Block a user