Plaid integration
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('Account Subtype', {
|
||||||
|
refresh: function(frm) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
134
erpnext/accounts/doctype/account_subtype/account_subtype.json
Normal file
134
erpnext/accounts/doctype/account_subtype/account_subtype.json
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
{
|
||||||
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
|
"allow_import": 1,
|
||||||
|
"allow_rename": 1,
|
||||||
|
"autoname": "field:account_subtype",
|
||||||
|
"beta": 0,
|
||||||
|
"creation": "2018-10-25 15:46:08.054586",
|
||||||
|
"custom": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "account_subtype",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "Account Subtype",
|
||||||
|
"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": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_web_view": 0,
|
||||||
|
"hide_heading": 0,
|
||||||
|
"hide_toolbar": 0,
|
||||||
|
"idx": 0,
|
||||||
|
"image_view": 0,
|
||||||
|
"in_create": 0,
|
||||||
|
"is_submittable": 0,
|
||||||
|
"issingle": 0,
|
||||||
|
"istable": 0,
|
||||||
|
"max_attachments": 0,
|
||||||
|
"modified": "2018-10-25 15:47:03.841390",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Account Subtype",
|
||||||
|
"name_case": "",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"amend": 0,
|
||||||
|
"cancel": 0,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 0,
|
||||||
|
"import": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"set_user_permissions": 0,
|
||||||
|
"share": 1,
|
||||||
|
"submit": 0,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amend": 0,
|
||||||
|
"cancel": 0,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 0,
|
||||||
|
"import": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts Manager",
|
||||||
|
"set_user_permissions": 0,
|
||||||
|
"share": 1,
|
||||||
|
"submit": 0,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amend": 0,
|
||||||
|
"cancel": 0,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 0,
|
||||||
|
"import": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts User",
|
||||||
|
"set_user_permissions": 0,
|
||||||
|
"share": 1,
|
||||||
|
"submit": 0,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quick_entry": 1,
|
||||||
|
"read_only": 0,
|
||||||
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 0,
|
||||||
|
"track_seen": 0,
|
||||||
|
"track_views": 0
|
||||||
|
}
|
||||||
10
erpnext/accounts/doctype/account_subtype/account_subtype.py
Normal file
10
erpnext/accounts/doctype/account_subtype/account_subtype.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class AccountSubtype(Document):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
// rename this file from _test_[name] to test_[name] to activate
|
||||||
|
// and remove above this line
|
||||||
|
|
||||||
|
QUnit.test("test: Account Subtype", function (assert) {
|
||||||
|
let done = assert.async();
|
||||||
|
|
||||||
|
// number of asserts
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
frappe.run_serially([
|
||||||
|
// insert a new Account Subtype
|
||||||
|
() => frappe.tests.make('Account Subtype', [
|
||||||
|
// values to be set
|
||||||
|
{key: 'value'}
|
||||||
|
]),
|
||||||
|
() => {
|
||||||
|
assert.equal(cur_frm.doc.key, 'value');
|
||||||
|
},
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class TestAccountSubtype(unittest.TestCase):
|
||||||
|
pass
|
||||||
0
erpnext/accounts/doctype/account_type/__init__.py
Normal file
0
erpnext/accounts/doctype/account_type/__init__.py
Normal file
8
erpnext/accounts/doctype/account_type/account_type.js
Normal file
8
erpnext/accounts/doctype/account_type/account_type.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('Account Type', {
|
||||||
|
refresh: function(frm) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
134
erpnext/accounts/doctype/account_type/account_type.json
Normal file
134
erpnext/accounts/doctype/account_type/account_type.json
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
{
|
||||||
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
|
"allow_import": 1,
|
||||||
|
"allow_rename": 1,
|
||||||
|
"autoname": "field:account_type",
|
||||||
|
"beta": 0,
|
||||||
|
"creation": "2018-10-25 15:45:45.789963",
|
||||||
|
"custom": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "account_type",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "Account Type",
|
||||||
|
"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": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_web_view": 0,
|
||||||
|
"hide_heading": 0,
|
||||||
|
"hide_toolbar": 0,
|
||||||
|
"idx": 0,
|
||||||
|
"image_view": 0,
|
||||||
|
"in_create": 0,
|
||||||
|
"is_submittable": 0,
|
||||||
|
"issingle": 0,
|
||||||
|
"istable": 0,
|
||||||
|
"max_attachments": 0,
|
||||||
|
"modified": "2018-10-25 15:46:51.042604",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Account Type",
|
||||||
|
"name_case": "",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"amend": 0,
|
||||||
|
"cancel": 0,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 0,
|
||||||
|
"import": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"set_user_permissions": 0,
|
||||||
|
"share": 1,
|
||||||
|
"submit": 0,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amend": 0,
|
||||||
|
"cancel": 0,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 0,
|
||||||
|
"import": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts Manager",
|
||||||
|
"set_user_permissions": 0,
|
||||||
|
"share": 1,
|
||||||
|
"submit": 0,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amend": 0,
|
||||||
|
"cancel": 0,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 0,
|
||||||
|
"import": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts User",
|
||||||
|
"set_user_permissions": 0,
|
||||||
|
"share": 1,
|
||||||
|
"submit": 0,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quick_entry": 1,
|
||||||
|
"read_only": 0,
|
||||||
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 0,
|
||||||
|
"track_seen": 0,
|
||||||
|
"track_views": 0
|
||||||
|
}
|
||||||
10
erpnext/accounts/doctype/account_type/account_type.py
Normal file
10
erpnext/accounts/doctype/account_type/account_type.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class AccountType(Document):
|
||||||
|
pass
|
||||||
23
erpnext/accounts/doctype/account_type/test_account_type.js
Normal file
23
erpnext/accounts/doctype/account_type/test_account_type.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
// rename this file from _test_[name] to test_[name] to activate
|
||||||
|
// and remove above this line
|
||||||
|
|
||||||
|
QUnit.test("test: Account Type", function (assert) {
|
||||||
|
let done = assert.async();
|
||||||
|
|
||||||
|
// number of asserts
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
frappe.run_serially([
|
||||||
|
// insert a new Account Type
|
||||||
|
() => frappe.tests.make('Account Type', [
|
||||||
|
// values to be set
|
||||||
|
{key: 'value'}
|
||||||
|
]),
|
||||||
|
() => {
|
||||||
|
assert.equal(cur_frm.doc.key, 'value');
|
||||||
|
},
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
10
erpnext/accounts/doctype/account_type/test_account_type.py
Normal file
10
erpnext/accounts/doctype/account_type/test_account_type.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class TestAccountType(unittest.TestCase):
|
||||||
|
pass
|
||||||
@@ -2,7 +2,29 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Bank', {
|
frappe.ui.form.on('Bank', {
|
||||||
|
onload: function(frm) {
|
||||||
|
add_fields_to_mapping_table(frm);
|
||||||
|
},
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
|
add_fields_to_mapping_table(frm);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
let add_fields_to_mapping_table = function (frm) {
|
||||||
|
let options = []
|
||||||
|
|
||||||
|
frappe.model.with_doctype("Bank Transaction", function() {
|
||||||
|
let meta = frappe.get_meta("Bank Transaction")
|
||||||
|
meta.fields.forEach(value => {
|
||||||
|
if (!["Section Break", "Column Break"].includes(value.fieldtype)) {
|
||||||
|
options.push(value.fieldname);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
frappe.meta.get_docfield("Bank Transaction Mapping", "bank_transaction_field",
|
||||||
|
frm.doc.name).options = options;
|
||||||
|
|
||||||
|
frm.fields_dict.bank_transaction_mapping.grid.refresh();
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
@@ -15,6 +16,7 @@
|
|||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -42,6 +44,134 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
|
"unique": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 1,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "data_import_configuration_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Data Import Configuration",
|
||||||
|
"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,
|
||||||
|
"fieldname": "bank_transaction_mapping",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"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": "Bank Transaction Mapping",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Bank Transaction Mapping",
|
||||||
|
"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,
|
||||||
|
"fieldname": "section_break_4",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "plaid_access_token",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "Plaid Access Token",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -55,7 +185,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-04-07 17:00:21.246202",
|
"modified": "2018-10-25 15:20:38.837772",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank",
|
"name": "Bank",
|
||||||
@@ -64,7 +194,6 @@
|
|||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
@@ -90,5 +219,6 @@
|
|||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"track_changes": 1,
|
||||||
"track_seen": 0
|
"track_seen": 0,
|
||||||
|
"track_views": 0
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
@@ -61,7 +62,7 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Account",
|
"label": "GL Account",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Account",
|
"options": "Account",
|
||||||
@@ -111,6 +112,136 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "account_type",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Account Type",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Account Type",
|
||||||
|
"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,
|
||||||
|
"fieldname": "account_subtype",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Account Subtype",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Account Subtype",
|
||||||
|
"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,
|
||||||
|
"fieldname": "column_break_7",
|
||||||
|
"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": 1,
|
||||||
|
"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,
|
||||||
|
"fieldname": "is_default",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"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": "Is the Default Account",
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@@ -177,198 +308,6 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_7",
|
|
||||||
"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": 1,
|
|
||||||
"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,
|
|
||||||
"fieldname": "is_default",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"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": "Is Default",
|
|
||||||
"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,
|
|
||||||
"fieldname": "bank_account_no",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Bank Account No",
|
|
||||||
"length": 30,
|
|
||||||
"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,
|
|
||||||
"fieldname": "iban",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "IBAN",
|
|
||||||
"length": 25,
|
|
||||||
"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,
|
|
||||||
"fieldname": "branch_code",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Branch Code",
|
|
||||||
"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,
|
|
||||||
"fieldname": "swift_number",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"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": "SWIFT number",
|
|
||||||
"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_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@@ -386,6 +325,7 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
|
"label": "Party Details",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@@ -498,6 +438,197 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "account_details_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Account Details",
|
||||||
|
"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,
|
||||||
|
"fieldname": "iban",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "IBAN",
|
||||||
|
"length": 25,
|
||||||
|
"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,
|
||||||
|
"fieldname": "column_break_12",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "bank_account_no",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Bank Account No",
|
||||||
|
"length": 30,
|
||||||
|
"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,
|
||||||
|
"fieldname": "branch_code",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Branch Code",
|
||||||
|
"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,
|
||||||
|
"fieldname": "swift_number",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "SWIFT number",
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@@ -602,7 +733,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "column_break_12",
|
"fieldname": "column_break_13",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@@ -657,6 +788,133 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "integration_details_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Integration Details",
|
||||||
|
"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,
|
||||||
|
"fieldname": "integration_id",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "Integration ID",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "column_break_27",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "mask",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "Mask",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"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,
|
"has_web_view": 0,
|
||||||
@@ -669,7 +927,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-07-20 13:55:36.996465",
|
"modified": "2018-10-26 14:14:45.049414",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Account",
|
"name": "Bank Account",
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('Bank Transaction', {
|
||||||
|
refresh: function(frm) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
615
erpnext/accounts/doctype/bank_transaction/bank_transaction.json
Normal file
615
erpnext/accounts/doctype/bank_transaction/bank_transaction.json
Normal file
@@ -0,0 +1,615 @@
|
|||||||
|
{
|
||||||
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
|
"allow_import": 1,
|
||||||
|
"allow_rename": 0,
|
||||||
|
"autoname": "naming_series:",
|
||||||
|
"beta": 0,
|
||||||
|
"creation": "2018-10-22 18:19:02.784533",
|
||||||
|
"custom": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "ACC-BTN-.YYYY.-",
|
||||||
|
"fieldname": "naming_series",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"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": "Series",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"options": "ACC-BTN-.YYYY.-",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
|
"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": 1,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"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": "Date",
|
||||||
|
"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,
|
||||||
|
"fieldname": "column_break_2",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "Settled",
|
||||||
|
"fieldname": "status",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"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": "Status",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "\nPending\nSettled",
|
||||||
|
"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,
|
||||||
|
"fieldname": "bank_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Bank Account",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Bank Account",
|
||||||
|
"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,
|
||||||
|
"fieldname": "section_break_4",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "debit",
|
||||||
|
"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": "Debit",
|
||||||
|
"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,
|
||||||
|
"fieldname": "credit",
|
||||||
|
"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": "Credit",
|
||||||
|
"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,
|
||||||
|
"fieldname": "column_break_7",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "currency",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Currency",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "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,
|
||||||
|
"fieldname": "section_break_10",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "description",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Description",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"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,
|
||||||
|
"fieldname": "section_break_14",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "reference_number",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "Reference Number",
|
||||||
|
"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,
|
||||||
|
"fieldname": "transaction_id",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "Transaction ID",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "amended_from",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Amended From",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 1,
|
||||||
|
"options": "Bank Transaction",
|
||||||
|
"permlevel": 0,
|
||||||
|
"print_hide": 1,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"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,
|
||||||
|
"hide_heading": 0,
|
||||||
|
"hide_toolbar": 0,
|
||||||
|
"idx": 0,
|
||||||
|
"image_view": 0,
|
||||||
|
"in_create": 0,
|
||||||
|
"is_submittable": 1,
|
||||||
|
"issingle": 0,
|
||||||
|
"istable": 0,
|
||||||
|
"max_attachments": 0,
|
||||||
|
"modified": "2018-10-26 15:58:53.400200",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Bank Transaction",
|
||||||
|
"name_case": "",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"amend": 0,
|
||||||
|
"cancel": 1,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 0,
|
||||||
|
"import": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"set_user_permissions": 0,
|
||||||
|
"share": 1,
|
||||||
|
"submit": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amend": 0,
|
||||||
|
"cancel": 1,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 0,
|
||||||
|
"import": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts Manager",
|
||||||
|
"set_user_permissions": 0,
|
||||||
|
"share": 1,
|
||||||
|
"submit": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"amend": 0,
|
||||||
|
"cancel": 0,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 0,
|
||||||
|
"import": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts User",
|
||||||
|
"set_user_permissions": 0,
|
||||||
|
"share": 1,
|
||||||
|
"submit": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quick_entry": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 0,
|
||||||
|
"track_seen": 0,
|
||||||
|
"track_views": 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class BankTransaction(Document):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
import json
|
||||||
|
from frappe.utils import getdate
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def upload_bank_statement():
|
||||||
|
if getattr(frappe, "uploaded_file", None):
|
||||||
|
with open(frappe.uploaded_file, "rb") as upfile:
|
||||||
|
fcontent = upfile.read()
|
||||||
|
else:
|
||||||
|
from frappe.utils.file_manager import get_uploaded_content
|
||||||
|
fname, fcontent = get_uploaded_content()
|
||||||
|
|
||||||
|
if frappe.safe_encode(fname).lower().endswith("csv"):
|
||||||
|
from frappe.utils.csvutils import read_csv_content
|
||||||
|
rows = read_csv_content(fcontent, False)
|
||||||
|
|
||||||
|
elif frappe.safe_encode(fname).lower().endswith("xlsx"):
|
||||||
|
from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
|
||||||
|
rows = read_xlsx_file_from_attached_file(fcontent=fcontent)
|
||||||
|
|
||||||
|
columns = rows[0]
|
||||||
|
rows.pop(0)
|
||||||
|
data = rows
|
||||||
|
return {"columns": columns, "data": data}
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def create_bank_entries(columns, data, bank_account):
|
||||||
|
bank_account = json.loads(bank_account)
|
||||||
|
header_map = get_header_mapping(columns, bank_account)
|
||||||
|
|
||||||
|
for d in json.loads(data):
|
||||||
|
fields = {}
|
||||||
|
for key, value in header_map.iteritems():
|
||||||
|
fields.update({key: d[int(value)-1]})
|
||||||
|
|
||||||
|
|
||||||
|
bank_transaction = frappe.get_doc({
|
||||||
|
"doctype": "Bank Transaction"
|
||||||
|
})
|
||||||
|
bank_transaction.update(fields)
|
||||||
|
bank_transaction.date = getdate(bank_transaction.date)
|
||||||
|
bank_transaction.bank_account = bank_account["name"]
|
||||||
|
bank_transaction.insert()
|
||||||
|
|
||||||
|
return 'success'
|
||||||
|
|
||||||
|
def get_header_mapping(columns, bank_account):
|
||||||
|
mapping = get_bank_mapping(bank_account)
|
||||||
|
|
||||||
|
header_map = {}
|
||||||
|
for column in json.loads(columns):
|
||||||
|
if column["content"] in mapping:
|
||||||
|
header_map.update({mapping[column["content"]]: column["colIndex"]})
|
||||||
|
|
||||||
|
return header_map
|
||||||
|
|
||||||
|
def get_bank_mapping(bank_account):
|
||||||
|
bank_name = frappe.db.get_value("Bank Account", bank_account["name"], "bank")
|
||||||
|
bank = frappe.get_doc("Bank", bank_name)
|
||||||
|
|
||||||
|
mapping = {row.file_field:row.bank_transaction_field for row in bank.bank_transaction_mapping}
|
||||||
|
|
||||||
|
return mapping
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
// rename this file from _test_[name] to test_[name] to activate
|
||||||
|
// and remove above this line
|
||||||
|
|
||||||
|
QUnit.test("test: Bank Transaction", function (assert) {
|
||||||
|
let done = assert.async();
|
||||||
|
|
||||||
|
// number of asserts
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
frappe.run_serially([
|
||||||
|
// insert a new Bank Transaction
|
||||||
|
() => frappe.tests.make('Bank Transaction', [
|
||||||
|
// values to be set
|
||||||
|
{key: 'value'}
|
||||||
|
]),
|
||||||
|
() => {
|
||||||
|
assert.equal(cur_frm.doc.key, 'value');
|
||||||
|
},
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class TestBankTransaction(unittest.TestCase):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
{
|
||||||
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
|
"allow_import": 0,
|
||||||
|
"allow_rename": 0,
|
||||||
|
"beta": 0,
|
||||||
|
"creation": "2018-10-24 15:24:56.713277",
|
||||||
|
"custom": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "bank_transaction_field",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Field in Bank Transaction",
|
||||||
|
"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": 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,
|
||||||
|
"fieldname": "file_field",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Column in Bank File",
|
||||||
|
"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": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"has_web_view": 0,
|
||||||
|
"hide_heading": 0,
|
||||||
|
"hide_toolbar": 0,
|
||||||
|
"idx": 0,
|
||||||
|
"image_view": 0,
|
||||||
|
"in_create": 0,
|
||||||
|
"is_submittable": 0,
|
||||||
|
"issingle": 0,
|
||||||
|
"istable": 1,
|
||||||
|
"max_attachments": 0,
|
||||||
|
"modified": "2018-10-24 15:24:56.713277",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Bank Transaction Mapping",
|
||||||
|
"name_case": "",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"quick_entry": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 0,
|
||||||
|
"track_seen": 0,
|
||||||
|
"track_views": 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class BankTransactionMapping(Document):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
from plaid import Client
|
||||||
|
from plaid.errors import APIError, ItemError
|
||||||
|
|
||||||
|
class PlaidConnector():
|
||||||
|
def __init__(self, access_token=None):
|
||||||
|
|
||||||
|
if not(frappe.conf.get("plaid_client_id") and frappe.conf.get("plaid_secret") and frappe.conf.get("plaid_public_key")):
|
||||||
|
frappe.throw(_("Please complete your Plaid API configuration before synchronizing your account"))
|
||||||
|
|
||||||
|
self.config = {
|
||||||
|
"plaid_client_id": frappe.conf.get("plaid_client_id"),
|
||||||
|
"plaid_secret": frappe.conf.get("plaid_secret"),
|
||||||
|
"plaid_public_key": frappe.conf.get("plaid_public_key"),
|
||||||
|
"plaid_env": frappe.conf.get("plaid_env")
|
||||||
|
}
|
||||||
|
|
||||||
|
self.client = Client(client_id=self.config["plaid_client_id"],
|
||||||
|
secret=self.config["plaid_secret"],
|
||||||
|
public_key=self.config["plaid_public_key"],
|
||||||
|
environment=self.config["plaid_env"]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.access_token = access_token
|
||||||
|
|
||||||
|
def get_access_token(self, public_token):
|
||||||
|
if public_token is None:
|
||||||
|
frappe.log_error(_("Public token is missing for this bank"), _("Plaid public token error"))
|
||||||
|
|
||||||
|
response = self.client.Item.public_token.exchange(public_token)
|
||||||
|
access_token = response['access_token']
|
||||||
|
|
||||||
|
return access_token
|
||||||
|
|
||||||
|
def auth(self):
|
||||||
|
try:
|
||||||
|
print(self.access_token)
|
||||||
|
self.client.Auth.get(self.access_token)
|
||||||
|
print("Authentication successful.....")
|
||||||
|
except ItemError as e:
|
||||||
|
if e.code == 'ITEM_LOGIN_REQUIRED':
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
except APIError as e:
|
||||||
|
if e.code == 'PLANNED_MAINTENANCE':
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
except requests.Timeout:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
frappe.log_error(frappe.get_traceback(), _("Plaid authentication error"))
|
||||||
|
frappe.msgprint({"title": _("Authentication Failed"), "message":e, "raise_exception":1, "indicator":'red'})
|
||||||
|
|
||||||
|
def get_transactions(self, start_date, end_date, account_id=None):
|
||||||
|
try:
|
||||||
|
self.auth()
|
||||||
|
if account_id:
|
||||||
|
account_ids = [account_id]
|
||||||
|
|
||||||
|
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))
|
||||||
|
transactions.extend(response['transactions'])
|
||||||
|
return transactions
|
||||||
|
except Exception:
|
||||||
|
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('Plaid Settings', {
|
||||||
|
refresh: function(frm) {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
connect_btn: function(frm) {
|
||||||
|
frappe.set_route('bankreconciliation/synchronization');
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
{
|
||||||
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
|
"allow_import": 0,
|
||||||
|
"allow_rename": 0,
|
||||||
|
"beta": 0,
|
||||||
|
"creation": "2018-10-25 10:02:48.656165",
|
||||||
|
"custom": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "enabled",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"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": "Enabled",
|
||||||
|
"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,
|
||||||
|
"depends_on": "eval:doc.enabled==1",
|
||||||
|
"fieldname": "connect_btn",
|
||||||
|
"fieldtype": "Button",
|
||||||
|
"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": "Connect with plaid",
|
||||||
|
"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,
|
||||||
|
"depends_on": "eval:doc.enabled==1",
|
||||||
|
"fieldname": "section_break_3",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "last_sync_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"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": "Last Synchronization Date",
|
||||||
|
"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,
|
||||||
|
"hide_heading": 0,
|
||||||
|
"hide_toolbar": 0,
|
||||||
|
"idx": 0,
|
||||||
|
"image_view": 0,
|
||||||
|
"in_create": 0,
|
||||||
|
"is_submittable": 0,
|
||||||
|
"issingle": 1,
|
||||||
|
"istable": 0,
|
||||||
|
"max_attachments": 0,
|
||||||
|
"modified": "2018-10-26 17:28:47.689735",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "ERPNext Integrations",
|
||||||
|
"name": "Plaid Settings",
|
||||||
|
"name_case": "",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"amend": 0,
|
||||||
|
"cancel": 0,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 0,
|
||||||
|
"if_owner": 0,
|
||||||
|
"import": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 0,
|
||||||
|
"role": "System Manager",
|
||||||
|
"set_user_permissions": 0,
|
||||||
|
"share": 1,
|
||||||
|
"submit": 0,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quick_entry": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 0,
|
||||||
|
"track_seen": 0,
|
||||||
|
"track_views": 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
import json
|
||||||
|
from frappe import _
|
||||||
|
from frappe.model.document import Document
|
||||||
|
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 frappe.utils import getdate, formatdate, today, add_months
|
||||||
|
|
||||||
|
class PlaidSettings(Document):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def plaid_configuration():
|
||||||
|
return {"plaid_public_key": frappe.conf.get("plaid_public_key") or None, "plaid_env": frappe.conf.get("plaid_env") or None, "client_name": frappe.local.site }
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def add_institution(token, response):
|
||||||
|
response = json.loads(response)
|
||||||
|
frappe.log_error(response)
|
||||||
|
|
||||||
|
plaid = PlaidConnector()
|
||||||
|
access_token = plaid.get_access_token(token)
|
||||||
|
|
||||||
|
if not frappe.db.exists("Bank", response["institution"]["name"]):
|
||||||
|
try:
|
||||||
|
bank = frappe.get_doc({
|
||||||
|
"doctype": "Bank",
|
||||||
|
"bank_name": response["institution"]["name"],
|
||||||
|
"plaid_access_token": access_token
|
||||||
|
})
|
||||||
|
bank.insert()
|
||||||
|
except Exception:
|
||||||
|
frappe.throw(frappe.get_traceback())
|
||||||
|
|
||||||
|
else:
|
||||||
|
bank = frappe.get_doc("Bank", response["institution"]["name"])
|
||||||
|
bank.plaid_access_token = access_token
|
||||||
|
bank.save()
|
||||||
|
|
||||||
|
return bank
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def add_bank_accounts(response, bank):
|
||||||
|
response = json.loads(response)
|
||||||
|
bank = json.loads(bank)
|
||||||
|
company = "Dokos"
|
||||||
|
result = []
|
||||||
|
default_gl_account = get_default_bank_cash_account(company, "Bank")
|
||||||
|
|
||||||
|
for account in response["accounts"]:
|
||||||
|
acc_type = frappe.db.get_value("Account Type", account["type"])
|
||||||
|
if not acc_type:
|
||||||
|
add_account_type(account["type"])
|
||||||
|
|
||||||
|
acc_subtype = frappe.db.get_value("Account Subtype", account["subtype"])
|
||||||
|
if not acc_subtype:
|
||||||
|
add_account_subtype(account["subtype"])
|
||||||
|
|
||||||
|
if not frappe.db.exists("Bank Account", dict(integration_id=account["id"])):
|
||||||
|
try:
|
||||||
|
new_account = frappe.get_doc({
|
||||||
|
"doctype": "Bank Account",
|
||||||
|
"bank": bank["bank_name"],
|
||||||
|
"account": default_gl_account.account,
|
||||||
|
"account_name": account["name"],
|
||||||
|
"account_type": account["type"] or "",
|
||||||
|
"account_subtype": account["subtype"] or "",
|
||||||
|
"mask": account["mask"] or "",
|
||||||
|
"integration_id": account["id"],
|
||||||
|
"is_company_account": 1,
|
||||||
|
"company": company
|
||||||
|
})
|
||||||
|
new_account.insert()
|
||||||
|
|
||||||
|
result.append(new_account.name)
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
frappe.throw(frappe.get_traceback())
|
||||||
|
|
||||||
|
else:
|
||||||
|
result.append(frappe.db.get_value("Bank Account", dict(integration_id=account["id"]), "name"))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def add_account_type(account_type):
|
||||||
|
try:
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Account Type",
|
||||||
|
"account_type": account_type
|
||||||
|
}).insert()
|
||||||
|
except:
|
||||||
|
frappe.throw(frappe.get_traceback())
|
||||||
|
|
||||||
|
|
||||||
|
def add_account_subtype(account_subtype):
|
||||||
|
try:
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Account Subtype",
|
||||||
|
"account_subtype": account_subtype
|
||||||
|
}).insert()
|
||||||
|
except:
|
||||||
|
frappe.throw(frappe.get_traceback())
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def sync_transactions(bank, bank_account=None):
|
||||||
|
|
||||||
|
last_sync_date = frappe.db.get_value("Plaid Settings", None, "last_sync_date")
|
||||||
|
if last_sync_date:
|
||||||
|
start_date = formatdate(last_sync_date, "YYYY-MM-dd")
|
||||||
|
else:
|
||||||
|
start_date = formatdate(add_months(today(), -12), "YYYY-MM-dd")
|
||||||
|
end_date = formatdate(today(), "YYYY-MM-dd")
|
||||||
|
|
||||||
|
try:
|
||||||
|
transactions = get_transactions(bank=bank, bank_account=bank_account, start_date=start_date, end_date=end_date)
|
||||||
|
result = []
|
||||||
|
if transactions:
|
||||||
|
for transaction in transactions:
|
||||||
|
result.append(new_bank_transaction(transaction))
|
||||||
|
|
||||||
|
frappe.db.set_value("Plaid Settings", None, "last_sync_date", getdate(end_date))
|
||||||
|
|
||||||
|
return result
|
||||||
|
except Exception:
|
||||||
|
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
|
||||||
|
|
||||||
|
|
||||||
|
def get_transactions(bank, bank_account=None, start_date=None, end_date=None):
|
||||||
|
access_token = None
|
||||||
|
|
||||||
|
if bank_account:
|
||||||
|
related_bank = frappe.db.get_values("Bank Account", dict(account_name=bank_account), ["bank", "integration_id"], as_dict=True)
|
||||||
|
access_token = frappe.db.get_value("Bank", related_bank[0].bank, "plaid_access_token")
|
||||||
|
account_id = related_bank[0].integration_id
|
||||||
|
|
||||||
|
else:
|
||||||
|
access_token = frappe.db.get_value("Bank", bank, "plaid_access_token")
|
||||||
|
account_id = None
|
||||||
|
|
||||||
|
plaid = PlaidConnector(access_token)
|
||||||
|
transactions = plaid.get_transactions(start_date=start_date, end_date=end_date, account_id=account_id)
|
||||||
|
|
||||||
|
return transactions
|
||||||
|
|
||||||
|
def new_bank_transaction(transaction):
|
||||||
|
result = []
|
||||||
|
|
||||||
|
bank_account = frappe.db.get_value("Bank Account", dict(integration_id=transaction["account_id"]))
|
||||||
|
|
||||||
|
if float(transaction["amount"]) >= 0:
|
||||||
|
debit = float(transaction["amount"])
|
||||||
|
credit = 0
|
||||||
|
else:
|
||||||
|
debit = 0
|
||||||
|
credit = abs(float(transaction["amount"]))
|
||||||
|
|
||||||
|
status = "Pending" if transaction["pending"] == "True" else "Settled"
|
||||||
|
|
||||||
|
if not frappe.db.exists("Bank Transaction", dict(transaction_id=transaction["transaction_id"])):
|
||||||
|
try:
|
||||||
|
new_transaction = frappe.get_doc({
|
||||||
|
"doctype": "Bank Transaction",
|
||||||
|
"date": getdate(transaction["date"]),
|
||||||
|
"status": status,
|
||||||
|
"bank_account": bank_account,
|
||||||
|
"debit": debit,
|
||||||
|
"credit": credit,
|
||||||
|
"currency": transaction["iso_currency_code"],
|
||||||
|
"description": transaction["name"]
|
||||||
|
})
|
||||||
|
new_transaction.insert()
|
||||||
|
|
||||||
|
result.append(new_transaction.name)
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
frappe.throw(frappe.get_traceback())
|
||||||
|
|
||||||
|
return result
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
// rename this file from _test_[name] to test_[name] to activate
|
||||||
|
// and remove above this line
|
||||||
|
|
||||||
|
QUnit.test("test: Plaid Settings", function (assert) {
|
||||||
|
let done = assert.async();
|
||||||
|
|
||||||
|
// number of asserts
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
frappe.run_serially([
|
||||||
|
// insert a new Plaid Settings
|
||||||
|
() => frappe.tests.make('Plaid Settings', [
|
||||||
|
// values to be set
|
||||||
|
{key: 'value'}
|
||||||
|
]),
|
||||||
|
() => {
|
||||||
|
assert.equal(cur_frm.doc.key, 'value');
|
||||||
|
},
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class TestPlaidSettings(unittest.TestCase):
|
||||||
|
pass
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"css/erpnext.css": [
|
"css/erpnext.css": [
|
||||||
"public/less/erpnext.less",
|
"public/less/erpnext.less",
|
||||||
"public/less/hub.less"
|
"public/less/hub.less",
|
||||||
|
"public/less/bankreconciliation.less"
|
||||||
],
|
],
|
||||||
"css/marketplace.css": [
|
"css/marketplace.css": [
|
||||||
"public/less/hub.less"
|
"public/less/hub.less"
|
||||||
@@ -16,6 +17,9 @@
|
|||||||
"js/marketplace.min.js": [
|
"js/marketplace.min.js": [
|
||||||
"public/js/hub/marketplace.js"
|
"public/js/hub/marketplace.js"
|
||||||
],
|
],
|
||||||
|
"js/bankreconciliation.min.js": [
|
||||||
|
"public/js/reconciliation/reconciliation_home.js"
|
||||||
|
],
|
||||||
"js/erpnext.min.js": [
|
"js/erpnext.min.js": [
|
||||||
"public/js/conf.js",
|
"public/js/conf.js",
|
||||||
"public/js/utils.js",
|
"public/js/utils.js",
|
||||||
@@ -48,7 +52,8 @@
|
|||||||
"public/js/utils/customer_quick_entry.js",
|
"public/js/utils/customer_quick_entry.js",
|
||||||
"public/js/education/student_button.html",
|
"public/js/education/student_button.html",
|
||||||
"public/js/education/assessment_result_tool.html",
|
"public/js/education/assessment_result_tool.html",
|
||||||
"public/js/hub/hub_factory.js"
|
"public/js/hub/hub_factory.js",
|
||||||
|
"public/js/reconciliation/reconciliation_factory.js"
|
||||||
],
|
],
|
||||||
"js/item-dashboard.min.js": [
|
"js/item-dashboard.min.js": [
|
||||||
"stock/dashboard/item_dashboard.html",
|
"stock/dashboard/item_dashboard.html",
|
||||||
|
|||||||
81
erpnext/public/js/reconciliation/Home.vue
Normal file
81
erpnext/public/js/reconciliation/Home.vue
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="bankreconciliation" class="bankreconciliation" :data-page-name="current_page">
|
||||||
|
<component
|
||||||
|
:is="current_page.component"
|
||||||
|
v-bind="{ getBankAccounts }"
|
||||||
|
:company='company'
|
||||||
|
:accounts='accounts'
|
||||||
|
>
|
||||||
|
</component>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import Dashboard from './pages/Dashboard.vue';
|
||||||
|
import Upload from './pages/Upload.vue';
|
||||||
|
import Reconciliation from './pages/Reconciliation.vue';
|
||||||
|
|
||||||
|
function get_route_map() {
|
||||||
|
return {
|
||||||
|
'bankreconciliation/home': {
|
||||||
|
'component': Dashboard
|
||||||
|
},
|
||||||
|
'bankreconciliation/upload': {
|
||||||
|
'component': Upload
|
||||||
|
},
|
||||||
|
'bankreconciliation/reconciliation': {
|
||||||
|
'component': Reconciliation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
props: ['initCompany'],
|
||||||
|
components: {
|
||||||
|
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
current_page: this.get_current_page(),
|
||||||
|
company: this.initCompany,
|
||||||
|
accounts: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
erpnext.bankreconciliation.on('company_changed', (e) => {
|
||||||
|
this.company = e;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
frappe.route.on('change', () => {
|
||||||
|
if (frappe.get_route()[0] === 'bankreconciliation') {
|
||||||
|
this.set_current_page();
|
||||||
|
frappe.utils.scroll_to(0);
|
||||||
|
$("body").attr("data-route", frappe.get_route_str());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
set_current_page() {
|
||||||
|
this.current_page = this.get_current_page();
|
||||||
|
},
|
||||||
|
get_current_page() {
|
||||||
|
const route_map = get_route_map();
|
||||||
|
const route = frappe.get_route_str();
|
||||||
|
if (route_map[route]) {
|
||||||
|
return route_map[route];
|
||||||
|
} else {
|
||||||
|
return route_map[route.substring(0, route.lastIndexOf('/')) + '/*'] || route_map['not_found']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getBankAccounts() {
|
||||||
|
frappe.db.get_list('Bank Account', {
|
||||||
|
fields: ['name', 'bank', 'bank_account_no', 'iban', 'branch_code', 'swift_number'],
|
||||||
|
filters: {'is_company_account': 1, 'company': this.company}
|
||||||
|
}).then((accounts) => {
|
||||||
|
this.accounts = accounts;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
49
erpnext/public/js/reconciliation/Sidebar.vue
Normal file
49
erpnext/public/js/reconciliation/Sidebar.vue
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="sidebar-container">
|
||||||
|
<ul class="list-unstyled bankreconciliation-sidebar-group" data-nav-buttons>
|
||||||
|
<li class="bankreconciliation-sidebar-item" v-for="item in items" :key="item.label" v-route="item.route">
|
||||||
|
{{ item.label }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: __('Dashboard'),
|
||||||
|
route: 'bankreconciliation/home'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __('Statement upload'),
|
||||||
|
route: 'bankreconciliation/upload'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __('Bank reconciliation'),
|
||||||
|
route: 'bankreconciliation/reconciliation',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.update_sidebar_state();
|
||||||
|
frappe.route.on('change', () => this.update_sidebar_state());
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
update_sidebar_state() {
|
||||||
|
const container = $(this.$refs['sidebar-container']);
|
||||||
|
const route = frappe.get_route();
|
||||||
|
const route_str = route.join('/');
|
||||||
|
const part_route_str = route.slice(0, 2).join('/');
|
||||||
|
const $sidebar_item = container.find(`[data-route="${route_str}"], [data-route="${part_route_str}"]`);
|
||||||
|
const $siblings = container.find('[data-route]');
|
||||||
|
$siblings.removeClass('active').addClass('text-muted');
|
||||||
|
$sidebar_item.addClass('active').removeClass('text-muted');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
78
erpnext/public/js/reconciliation/components/AccountCard.vue
Normal file
78
erpnext/public/js/reconciliation/components/AccountCard.vue
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<template>
|
||||||
|
<div class="col-md-3 col-sm-4 col-xs-6 account-card-container">
|
||||||
|
<div class="account-card text-center"
|
||||||
|
@click="on_click(account)"
|
||||||
|
>
|
||||||
|
<div v-bind:class="getClass">
|
||||||
|
<div class="ellipsis" :style="{ width: '85%' }">
|
||||||
|
<div class="account-card-title ellipsis bold">{{ title }}</div>
|
||||||
|
<div class="account-card-subtitle ellipsis text-muted" v-html='subtitle'></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'account-card',
|
||||||
|
props: ['account', 'account_id_fieldname', 'on_click', 'selected_account'],
|
||||||
|
computed: {
|
||||||
|
title() {
|
||||||
|
const account_name = this.account.name;
|
||||||
|
return account_name;
|
||||||
|
},
|
||||||
|
subtitle() {
|
||||||
|
return "Test"
|
||||||
|
},
|
||||||
|
getClass() {
|
||||||
|
let value = (this.account.name == this.selected_account.name) ? "account-card-header flex justify-between selected" : "account-card-header flex justify-between"
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
method: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@import "../../../../../../frappe/frappe/public/less/variables.less";
|
||||||
|
.account-card {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid @border-color;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover .account-card-overlay {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.account-card-header {
|
||||||
|
position: relative;
|
||||||
|
padding: 12px 15px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
.account-card-body {
|
||||||
|
position: relative;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
.account-card-overlay {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
.account-card-overlay-body {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.account-card-overlay-button {
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
bottom: 15px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<div class="bank-accounts-container">
|
||||||
|
<account-card
|
||||||
|
v-for="account in accounts"
|
||||||
|
:key="container_name + '_' +account[account_id_fieldname]"
|
||||||
|
:account="account"
|
||||||
|
:on_click="on_click"
|
||||||
|
:account_id_fieldname="account_id_fieldname"
|
||||||
|
:selected_account="selected_account"
|
||||||
|
>
|
||||||
|
</account-card>
|
||||||
|
<new-account-card
|
||||||
|
v-if="accounts.length > 0 && !show_plaid_link"
|
||||||
|
>
|
||||||
|
</new-account-card>
|
||||||
|
<PlaidLink
|
||||||
|
v-if="show_plaid_link"
|
||||||
|
:env="plaid_env"
|
||||||
|
:publicKey="plaid_public_key"
|
||||||
|
:clientName="client_name"
|
||||||
|
:product='["transactions", "auth"]'
|
||||||
|
v-bind="{ plaidSuccess }"
|
||||||
|
:subtitle="plaid_subtitle">
|
||||||
|
</PlaidLink>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import AccountCard from './AccountCard.vue';
|
||||||
|
import NewAccountCard from './NewAccountCard.vue';
|
||||||
|
import PlaidLink from '../components/PlaidLink.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'account-cards-container',
|
||||||
|
props: {
|
||||||
|
container_name: String,
|
||||||
|
accounts: Array,
|
||||||
|
account_id_fieldname: String,
|
||||||
|
is_local: Boolean,
|
||||||
|
on_click: Function,
|
||||||
|
editable: Boolean,
|
||||||
|
selected_account: Object,
|
||||||
|
show_plaid_link: Boolean,
|
||||||
|
plaid_env: String,
|
||||||
|
plaid_public_key: String,
|
||||||
|
client_name: String,
|
||||||
|
plaidSuccess: Function,
|
||||||
|
plaid_subtitle: String
|
||||||
|
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
AccountCard,
|
||||||
|
NewAccountCard,
|
||||||
|
PlaidLink
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
section_title: __("Please select a bank account"),
|
||||||
|
onSuccess: this.plaid_on_success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.bank-accounts-container {
|
||||||
|
margin: 0 -15px;
|
||||||
|
overflow: overlay;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
45
erpnext/public/js/reconciliation/components/EmptyState.vue
Normal file
45
erpnext/public/js/reconciliation/components/EmptyState.vue
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<div class="empty-state flex flex-column"
|
||||||
|
:class="{ 'bordered': bordered, 'align-center': centered, 'justify-center': centered }"
|
||||||
|
:style="{ height: height + 'px' }"
|
||||||
|
>
|
||||||
|
<p class="text-muted">{{ message }}</p>
|
||||||
|
<p v-if="action">
|
||||||
|
<button class="btn btn-default btn-xs"
|
||||||
|
@click="action.on_click"
|
||||||
|
>
|
||||||
|
{{ action.label }}
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'empty-state',
|
||||||
|
props: {
|
||||||
|
message: String,
|
||||||
|
bordered: Boolean,
|
||||||
|
height: Number,
|
||||||
|
action: Object,
|
||||||
|
centered: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
@import "../../../../../../frappe/frappe/public/less/variables.less";
|
||||||
|
.empty-state {
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
|
.empty-state.bordered {
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid @border-color;
|
||||||
|
border-style: dashed;
|
||||||
|
// bad, due to item card column layout, that is inner 15px margin
|
||||||
|
margin: 0 15px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<div class="col-md-3 col-sm-4 col-xs-6 new-account-card-container">
|
||||||
|
<div class="account-card text-center"
|
||||||
|
@click="on_click()"
|
||||||
|
>
|
||||||
|
<div class="account-card-header flex justify-between">
|
||||||
|
<div class="ellipsis">
|
||||||
|
<div class="new-account-card-text ellipsis text-muted" v-html='subtitle'></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'new-account-card',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
subtitle: __("Add a new account")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
on_click() {
|
||||||
|
frappe.new_doc("Bank Account")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@import "../../../../../../frappe/frappe/public/less/variables.less";
|
||||||
|
.account-card {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid @border-color;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-style: dashed;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover .account-card-overlay {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.account-card-header {
|
||||||
|
position: relative;
|
||||||
|
padding: 12px 15px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
.account-card-body {
|
||||||
|
position: relative;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
.account-card-overlay {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
.account-card-overlay-body {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.account-card-overlay-button {
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
bottom: 15px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
136
erpnext/public/js/reconciliation/components/PlaidLink.vue
Normal file
136
erpnext/public/js/reconciliation/components/PlaidLink.vue
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<div class="col-md-3 col-sm-4 col-xs-6 new-account-card-container">
|
||||||
|
<div class="account-card text-center"
|
||||||
|
@click="handleOnClick()"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
<div class="account-card-header flex justify-between">
|
||||||
|
<div class="ellipsis">
|
||||||
|
<div class="new-account-card-text ellipsis text-muted" v-html='subtitle'></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'PlaidLink',
|
||||||
|
props: {
|
||||||
|
plaidUrl: {
|
||||||
|
type: String,
|
||||||
|
default: 'https://cdn.plaid.com/link/v2/stable/link-initialize.js'
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
type: String,
|
||||||
|
default: 'sandbox'
|
||||||
|
},
|
||||||
|
institution: String,
|
||||||
|
selectAccount: Boolean,
|
||||||
|
token: String,
|
||||||
|
product: {
|
||||||
|
type: Array,
|
||||||
|
default: ["transactions"]
|
||||||
|
},
|
||||||
|
clientName: String,
|
||||||
|
publicKey: String,
|
||||||
|
webhook: String,
|
||||||
|
plaidSuccess: Function,
|
||||||
|
onExit: Function,
|
||||||
|
onEvent: Function,
|
||||||
|
subtitle: String
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.loadScript(this.plaidUrl)
|
||||||
|
.then(this.onScriptLoaded)
|
||||||
|
.catch(this.onScriptError)
|
||||||
|
},
|
||||||
|
beforeDestroy () {
|
||||||
|
if (window.linkHandler && window.linkHandler.open.lenth > 0) {
|
||||||
|
window.linkHandler.exit()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onScriptError (error) {
|
||||||
|
console.error('There was an issue loading the link-initialize.js script')
|
||||||
|
},
|
||||||
|
onScriptLoaded () {
|
||||||
|
window.linkHandler = window.Plaid.create({
|
||||||
|
clientName: this.clientName,
|
||||||
|
env: this.env,
|
||||||
|
key: this.publicKey,
|
||||||
|
onExit: this.onExit,
|
||||||
|
onEvent: this.onEvent,
|
||||||
|
onSuccess: this.plaidSuccess,
|
||||||
|
product: this.product,
|
||||||
|
selectAccount: this.selectAccount,
|
||||||
|
token: this.token,
|
||||||
|
webhook: this.webhook
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleOnClick () {
|
||||||
|
const institution = this.institution || null
|
||||||
|
if (window.linkHandler) {
|
||||||
|
window.linkHandler.open(institution)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loadScript (src) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
if (document.querySelector('script[src="' + src + '"]')) {
|
||||||
|
resolve()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const el = document.createElement('script')
|
||||||
|
el.type = 'text/javascript'
|
||||||
|
el.async = true
|
||||||
|
el.src = src
|
||||||
|
el.addEventListener('load', resolve)
|
||||||
|
el.addEventListener('error', reject)
|
||||||
|
el.addEventListener('abort', reject)
|
||||||
|
document.head.appendChild(el)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@import "../../../../../../frappe/frappe/public/less/variables.less";
|
||||||
|
.account-card {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid @border-color;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-style: dashed;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover .account-card-overlay {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.account-card-header {
|
||||||
|
position: relative;
|
||||||
|
padding: 12px 15px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
.account-card-body {
|
||||||
|
position: relative;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
.account-card-overlay {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
.account-card-overlay-body {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.account-card-overlay-button {
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
bottom: 15px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<template>
|
||||||
|
<tr class="transaction-card text-center"
|
||||||
|
@click="on_click(transaction)"
|
||||||
|
>
|
||||||
|
<td>{{ transaction.description }}</td>
|
||||||
|
<td>{{ amount }}</td>
|
||||||
|
<td>{{ transaction.currency }}</td>
|
||||||
|
<td>{{ date }}</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'transaction-card',
|
||||||
|
props: ['transaction', 'transaction_id_fieldname', 'on_click', 'selected_transaction'],
|
||||||
|
computed: {
|
||||||
|
amount() {
|
||||||
|
const amount = (parseFloat(this.transaction.credit) > 0) ? -Math.abs(parseFloat(this.transaction.credit)) : parseFloat(this.transaction.debit);
|
||||||
|
return amount;
|
||||||
|
},
|
||||||
|
date() {
|
||||||
|
const date = moment(this.transaction.date)
|
||||||
|
return frappe.datetime.obj_to_user(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@import "../../../../../../frappe/frappe/public/less/variables.less";
|
||||||
|
.transaction-card {
|
||||||
|
height: 60px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
td {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<div class="transactions-container">
|
||||||
|
<empty-state
|
||||||
|
v-if="transactions.length === 0"
|
||||||
|
:message="empty_state_message"
|
||||||
|
:action="empty_state_action"
|
||||||
|
:bordered="false"
|
||||||
|
:height="empty_state_height"
|
||||||
|
/>
|
||||||
|
<table class="table table-bordered table-hover" v-if="transactions.length > 0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{{ __('Description') }}</th>
|
||||||
|
<th>{{ __('Amount') }}</th>
|
||||||
|
<th>{{ __('Currency') }}</th>
|
||||||
|
<th>{{ __('Date') }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<transaction-card
|
||||||
|
v-for="transaction in transactions"
|
||||||
|
:key="container_name + '_' +transaction[transaction_id_fieldname]"
|
||||||
|
:transaction="transaction"
|
||||||
|
:on_click="on_click"
|
||||||
|
:transaction_id_fieldname="transaction_id_fieldname"
|
||||||
|
:selected_transaction="selected_transaction"
|
||||||
|
>
|
||||||
|
</transaction-card>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import TransactionCard from './TransactionCard.vue';
|
||||||
|
import EmptyState from './EmptyState.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'transactions-container',
|
||||||
|
props: {
|
||||||
|
container_name: String,
|
||||||
|
transactions: Array,
|
||||||
|
transaction_id_fieldname: String,
|
||||||
|
is_local: Boolean,
|
||||||
|
on_click: Function,
|
||||||
|
editable: Boolean,
|
||||||
|
empty_state_message: String,
|
||||||
|
empty_state_action: Object,
|
||||||
|
empty_state_height: Number,
|
||||||
|
empty_state_bordered: Boolean,
|
||||||
|
selected_transaction: Object
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
TransactionCard,
|
||||||
|
EmptyState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.transactions-container {
|
||||||
|
margin: 35px -15px;
|
||||||
|
overflow: overlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
tr {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
25
erpnext/public/js/reconciliation/pages/Dashboard.vue
Normal file
25
erpnext/public/js/reconciliation/pages/Dashboard.vue
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<div class="dashboard-container">
|
||||||
|
<div>
|
||||||
|
Dashboard
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['company'],
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
155
erpnext/public/js/reconciliation/pages/Reconciliation.vue
Normal file
155
erpnext/public/js/reconciliation/pages/Reconciliation.vue
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
<template>
|
||||||
|
<div class="reconciliation-container">
|
||||||
|
<bank-accounts-container
|
||||||
|
:container_name="page_title"
|
||||||
|
:accounts="accounts"
|
||||||
|
:account_id_fieldname="account_id_fieldname"
|
||||||
|
:on_click="select_account"
|
||||||
|
:empty_state_message="empty_state_message"
|
||||||
|
:selected_account="selected_account"
|
||||||
|
:show_plaid_link="show_plaid_link"
|
||||||
|
:plaid_env="plaid_env"
|
||||||
|
:plaid_public_key="plaid_public_key"
|
||||||
|
:client_name="client_name"
|
||||||
|
:plaidSuccess="plaid_success"
|
||||||
|
:plaid_subtitle="plaid_subtitle"
|
||||||
|
>
|
||||||
|
</bank-accounts-container>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div ref="from-date" class="col-xs-6"></div>
|
||||||
|
<div ref="to-date" class="col-xs-6"></div>
|
||||||
|
</div>
|
||||||
|
<div v-show="mandatory_fields_completed" class="text-center">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary"
|
||||||
|
@click="sync_account">
|
||||||
|
{{ __('Synchronize this account') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn-primary"
|
||||||
|
@click="get_transactions">
|
||||||
|
{{ __('Get unreconciled transactions') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<transactions-container
|
||||||
|
:container_name="page_title"
|
||||||
|
:transactions="transactions"
|
||||||
|
:transaction_id_fieldname="transaction_id_fieldname"
|
||||||
|
:on_click="select_transaction"
|
||||||
|
:empty_state_message="empty_state_message"
|
||||||
|
:selected_transaction="selected_transaction"
|
||||||
|
>
|
||||||
|
</transactions-container>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import BankAccountsContainer from '../components/BankAccountsContainer.vue';
|
||||||
|
import TransactionsContainer from '../components/TransactionsContainer.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
company: String,
|
||||||
|
accounts: Array,
|
||||||
|
getBankAccounts: Function
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
BankAccountsContainer,
|
||||||
|
TransactionsContainer
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
account_id_fieldname: 'name',
|
||||||
|
page_title: __('Accounts'),
|
||||||
|
empty_state_message: __(`Please select an account first.`),
|
||||||
|
selected_account: {},
|
||||||
|
bank_entries: {},
|
||||||
|
transactions: [],
|
||||||
|
transaction_id_fieldname: 'name',
|
||||||
|
selected_transaction: {},
|
||||||
|
client_name: "Test App",
|
||||||
|
plaid_env : null,
|
||||||
|
plaid_public_key: null,
|
||||||
|
show_plaid_link: false,
|
||||||
|
plaid_subtitle: __("Add a new account")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
let me = this;
|
||||||
|
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.plaid_configuration')
|
||||||
|
.then(result => {
|
||||||
|
me.plaid_env = result.plaid_env;
|
||||||
|
me.plaid_public_key = result.plaid_public_key;
|
||||||
|
me.client_name = result.client_name;
|
||||||
|
me.show_plaid_link = true;
|
||||||
|
})
|
||||||
|
|
||||||
|
this.getBankAccounts();
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
mandatory_fields_completed() {
|
||||||
|
if (this.selected_account.name !== undefined) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
select_account(account) {
|
||||||
|
if (this.selected_account == account) {
|
||||||
|
this.selected_account = {}
|
||||||
|
} else {
|
||||||
|
this.selected_account = account
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
get_transactions() {
|
||||||
|
frappe.db.get_list('Bank Transaction', {
|
||||||
|
fields: ['name', 'date', 'status', 'debit', 'credit', 'currency', 'description'],
|
||||||
|
filters: {"docstatus": 1},
|
||||||
|
or_filters: [['reference_number', '=', '']]
|
||||||
|
|
||||||
|
}).then((transactions) => {
|
||||||
|
this.transactions = transactions;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
plaid_success(token, response) {
|
||||||
|
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.add_institution', {token: token, response: response})
|
||||||
|
.then((result) => {
|
||||||
|
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.add_bank_accounts', {response: response, bank: result})
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
this.getBankAccounts();
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
sync_account() {
|
||||||
|
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.sync_transactions', {
|
||||||
|
bank: this.selected_account.bank,
|
||||||
|
bank_account: this.selected_account.name
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
this.get_transactions();
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
select_transaction() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
button {
|
||||||
|
margin: 25px 25px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
115
erpnext/public/js/reconciliation/pages/Upload.vue
Normal file
115
erpnext/public/js/reconciliation/pages/Upload.vue
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<bank-accounts-container
|
||||||
|
:container_name="page_title"
|
||||||
|
:accounts="accounts"
|
||||||
|
:account_id_fieldname="account_id_fieldname"
|
||||||
|
:on_click="select_account"
|
||||||
|
:empty_state_message="empty_state_message"
|
||||||
|
:selected_account="selected_account"
|
||||||
|
>
|
||||||
|
</bank-accounts-container>
|
||||||
|
|
||||||
|
<div v-show="selected_account.name !== undefined">
|
||||||
|
<hr>
|
||||||
|
<div ref="upload-container" class="upload-btn-container"></div>
|
||||||
|
<div class="table-container"></div>
|
||||||
|
|
||||||
|
<div v-show="datatable_not_empty">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary btn-xl"
|
||||||
|
@click="add_bank_entries">
|
||||||
|
{{ __('Add bank entries') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import DataTable from 'frappe-datatable';
|
||||||
|
import BankAccountsContainer from '../components/BankAccountsContainer.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
company: String,
|
||||||
|
accounts: Array,
|
||||||
|
getBankAccounts: Function
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
BankAccountsContainer
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
account_id_fieldname: 'name',
|
||||||
|
page_title: __('Accounts'),
|
||||||
|
empty_state_message: __(`You haven't added any bank account yet.`),
|
||||||
|
selected_account: {},
|
||||||
|
bank_entries: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getBankAccounts();
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.add_upload_section();
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
datatable_not_empty() {
|
||||||
|
return Object.keys(this.bank_entries).length > 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
add_upload_section() {
|
||||||
|
let me = this;
|
||||||
|
let wrapper = $(this.$refs['upload-container']);
|
||||||
|
frappe.upload.make({
|
||||||
|
parent: wrapper,
|
||||||
|
args: {
|
||||||
|
method: 'erpnext.accounts.doctype.bank_transaction.bank_transaction_upload.upload_bank_statement',
|
||||||
|
allow_multiple: 0
|
||||||
|
},
|
||||||
|
no_socketio: true,
|
||||||
|
sample_url: "e.g. http://example.com/somefile.csv",
|
||||||
|
callback: function(attachment, r) {
|
||||||
|
if (!r.exc && r.message) {
|
||||||
|
me.bank_entries = new DataTable('.table-container', {
|
||||||
|
columns: r.message.columns,
|
||||||
|
data: r.message.data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
select_account(account) {
|
||||||
|
if (this.selected_account == account) {
|
||||||
|
this.selected_account = {}
|
||||||
|
} else {
|
||||||
|
this.selected_account = account
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
upload_file() {
|
||||||
|
erpnext.bankreconciliation.upload_statement.show()
|
||||||
|
},
|
||||||
|
|
||||||
|
add_bank_entries() {
|
||||||
|
console.log(this.bank_entries.datamanager)
|
||||||
|
frappe.xcall('erpnext.accounts.doctype.bank_transaction.bank_transaction_upload.create_bank_entries',
|
||||||
|
{columns: this.bank_entries.datamanager.columns, data: this.bank_entries.datamanager.data, bank_account: this.selected_account}
|
||||||
|
).then((result) => {
|
||||||
|
console.log(result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
button {
|
||||||
|
margin-top: 35px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
29
erpnext/public/js/reconciliation/reconciliation_factory.js
Normal file
29
erpnext/public/js/reconciliation/reconciliation_factory.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
frappe.provide('erpnext.bankreconciliation');
|
||||||
|
|
||||||
|
frappe.views.bankreconciliationFactory = class bankreconciliationFactory extends frappe.views.Factory {
|
||||||
|
show() {
|
||||||
|
if (frappe.pages.bankreconciliation) {
|
||||||
|
frappe.container.change_to('bankreconciliation');
|
||||||
|
} else {
|
||||||
|
this.make('bankreconciliation');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
make(page_name) {
|
||||||
|
const assets = [
|
||||||
|
'/assets/js/bankreconciliation.min.js'
|
||||||
|
];
|
||||||
|
frappe.require(assets, () => {
|
||||||
|
erpnext.bankreconciliation.home = new erpnext.bankreconciliation.Home({
|
||||||
|
parent: this.make_page(true, page_name)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).on('toolbar_setup', () => {
|
||||||
|
$('#toolbar-user .navbar-reload').after(`
|
||||||
|
<li>
|
||||||
|
<a class="bankreconciliation-link" href="#bankreconciliation/home">${__("Bank Reconciliation")}</a>
|
||||||
|
</li>
|
||||||
|
`);
|
||||||
|
});
|
||||||
100
erpnext/public/js/reconciliation/reconciliation_home.js
Normal file
100
erpnext/public/js/reconciliation/reconciliation_home.js
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import Vue from 'vue/dist/vue.js';
|
||||||
|
import './vue-plugins';
|
||||||
|
|
||||||
|
import Home from './Home.vue';
|
||||||
|
import Sidebar from './Sidebar.vue';
|
||||||
|
|
||||||
|
import EventEmitter from '../hub/event_emitter';
|
||||||
|
|
||||||
|
frappe.provide('erpnext.bankreconciliation');
|
||||||
|
frappe.provide('frappe.route');
|
||||||
|
frappe.provide('frappe.upload');
|
||||||
|
|
||||||
|
$.extend(erpnext.bankreconciliation, EventEmitter.prototype);
|
||||||
|
$.extend(frappe.route, EventEmitter.prototype);
|
||||||
|
|
||||||
|
erpnext.bankreconciliation.Home = class bankreconciliation {
|
||||||
|
constructor({ parent }) {
|
||||||
|
this.$parent = $(parent);
|
||||||
|
this.page = parent.page;
|
||||||
|
this.company = frappe.defaults.get_user_default("Company");
|
||||||
|
this.setup_header();
|
||||||
|
this.make_sidebar();
|
||||||
|
this.make_body();
|
||||||
|
this.setup_events();
|
||||||
|
this.set_secondary_action();
|
||||||
|
}
|
||||||
|
|
||||||
|
make_sidebar() {
|
||||||
|
this.$sidebar = this.$parent.find('.layout-side-section').addClass('hidden-xs');
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: $('<div>').appendTo(this.$sidebar)[0],
|
||||||
|
render: h => h(Sidebar)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
make_body() {
|
||||||
|
let me = this;
|
||||||
|
me.$body = me.$parent.find('.layout-main-section');
|
||||||
|
me.$page_container = $('<div class="bankreconciliation-page-container">').appendTo(this.$body);
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: me.$page_container[0],
|
||||||
|
render(h) {
|
||||||
|
return h(Home, {props: { initCompany: me.company}})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_header() {
|
||||||
|
this.page.set_title(__('Bank Reconciliation'));
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_events() {
|
||||||
|
this.$parent.on('click', '[data-route]', (e) => {
|
||||||
|
const $target = $(e.currentTarget);
|
||||||
|
const route = $target.data().route;
|
||||||
|
frappe.set_route(route);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$parent.on('click', '[data-action]', e => {
|
||||||
|
const $target = $(e.currentTarget);
|
||||||
|
const action = $target.data().action;
|
||||||
|
|
||||||
|
if (action && this[action]) {
|
||||||
|
this[action].apply(this, $target);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
set_secondary_action() {
|
||||||
|
let me = this;
|
||||||
|
this.page.set_secondary_action(this.company, function () {
|
||||||
|
me.company_selection_dialog();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
company_selection_dialog() {
|
||||||
|
let me = this;
|
||||||
|
let dialog = new frappe.ui.Dialog({
|
||||||
|
title: __('Select another company'),
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
"label": "Company",
|
||||||
|
"fieldname": "company",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Company"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
primary_action_label: __('Confirm'),
|
||||||
|
primary_action: function(v) {
|
||||||
|
me.company = v.company;
|
||||||
|
erpnext.bankreconciliation.trigger('company_changed', v.company);
|
||||||
|
me.set_secondary_action();
|
||||||
|
dialog.hide();
|
||||||
|
},
|
||||||
|
})
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
};
|
||||||
17
erpnext/public/js/reconciliation/vue-plugins.js
Normal file
17
erpnext/public/js/reconciliation/vue-plugins.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import Vue from 'vue/dist/vue.js';
|
||||||
|
|
||||||
|
Vue.prototype.__ = window.__;
|
||||||
|
Vue.prototype.frappe = window.frappe;
|
||||||
|
|
||||||
|
Vue.directive('route', {
|
||||||
|
bind(el, binding) {
|
||||||
|
const route = binding.value;
|
||||||
|
if (!route) return;
|
||||||
|
el.classList.add('cursor-pointer');
|
||||||
|
el.dataset.route = route;
|
||||||
|
el.addEventListener('click', () => frappe.set_route(route));
|
||||||
|
},
|
||||||
|
unbind(el) {
|
||||||
|
el.classList.remove('cursor-pointer');
|
||||||
|
}
|
||||||
|
});
|
||||||
71
erpnext/public/less/bankreconciliation.less
Normal file
71
erpnext/public/less/bankreconciliation.less
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
|
||||||
|
@import "variables.less";
|
||||||
|
@import (reference) 'common.less';
|
||||||
|
|
||||||
|
body[data-route*="bankreconciliation"] {
|
||||||
|
|
||||||
|
.layout-side-section {
|
||||||
|
padding-top: 25px;
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-right: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-route], [data-action] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-main-section {
|
||||||
|
border: none;
|
||||||
|
font-size: @text-medium;
|
||||||
|
padding-top: 25px;
|
||||||
|
|
||||||
|
@media (max-width: @screen-xs) {
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input, textarea {
|
||||||
|
font-size: @text-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankreconciliation-sidebar {
|
||||||
|
padding-top: 25px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankreconciliation-sidebar-group {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bankreconciliation-sidebar-item {
|
||||||
|
padding: 5px 8px;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
|
||||||
|
&.active, &:hover:not(.is-title) {
|
||||||
|
border-color: @border-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container {
|
||||||
|
.frappe-control {
|
||||||
|
max-width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-btn-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-card {
|
||||||
|
.selected {
|
||||||
|
background-color: #e2f4d0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,3 +7,4 @@ braintree
|
|||||||
gocardless_pro
|
gocardless_pro
|
||||||
woocommerce
|
woocommerce
|
||||||
pandas
|
pandas
|
||||||
|
plaid-python
|
||||||
Reference in New Issue
Block a user