Merge branch 'develop' into dev-work-order-bugs
This commit is contained in:
commit
4432a874de
@ -720,7 +720,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
|
||||
$.each(frm.doc.references || [], function(i, row) {
|
||||
row.allocated_amount = 0 //If allocate payment amount checkbox is unchecked, set zero to allocate amount
|
||||
if(frappe.flags.allocate_payment_amount){
|
||||
if(frappe.flags.allocate_payment_amount != 0){
|
||||
if(row.outstanding_amount > 0 && allocated_positive_outstanding > 0) {
|
||||
if(row.outstanding_amount >= allocated_positive_outstanding) {
|
||||
row.allocated_amount = allocated_positive_outstanding;
|
||||
|
@ -126,7 +126,7 @@ class PaymentEntry(AccountsController):
|
||||
if not self.party:
|
||||
frappe.throw(_("Party is mandatory"))
|
||||
|
||||
_party_name = "title" if self.party_type == "Student" else self.party_type.lower() + "_name"
|
||||
_party_name = "title" if self.party_type in ("Student", "Shareholder") else self.party_type.lower() + "_name"
|
||||
self.party_name = frappe.db.get_value(self.party_type, self.party, _party_name)
|
||||
|
||||
if self.party:
|
||||
|
@ -86,17 +86,23 @@ class ShareTransfer(Document):
|
||||
frappe.throw(_('The field From Shareholder cannot be blank'))
|
||||
if self.from_folio_no is None or self.from_folio_no is '':
|
||||
self.to_folio_no = self.autoname_folio(self.to_shareholder)
|
||||
if self.asset_account is None:
|
||||
frappe.throw(_('The field Asset Account cannot be blank'))
|
||||
elif (self.transfer_type == 'Issue'):
|
||||
self.from_shareholder = ''
|
||||
if self.to_shareholder is None or self.to_shareholder == '':
|
||||
frappe.throw(_('The field To Shareholder cannot be blank'))
|
||||
if self.to_folio_no is None or self.to_folio_no is '':
|
||||
self.to_folio_no = self.autoname_folio(self.to_shareholder)
|
||||
if self.asset_account is None:
|
||||
frappe.throw(_('The field Asset Account cannot be blank'))
|
||||
else:
|
||||
if self.from_shareholder is None or self.to_shareholder is None:
|
||||
frappe.throw(_('The fields From Shareholder and To Shareholder cannot be blank'))
|
||||
if self.to_folio_no is None or self.to_folio_no is '':
|
||||
self.to_folio_no = self.autoname_folio(self.to_shareholder)
|
||||
if self.equity_or_liability_account is None:
|
||||
frappe.throw(_('The field Equity/Liability Account cannot be blank'))
|
||||
if self.from_shareholder == self.to_shareholder:
|
||||
frappe.throw(_('The seller and the buyer cannot be the same'))
|
||||
if self.no_of_shares != self.to_no - self.from_no + 1:
|
||||
|
@ -15,67 +15,74 @@ class TestShareTransfer(unittest.TestCase):
|
||||
frappe.db.sql("delete from `tabShare Balance`")
|
||||
share_transfers = [
|
||||
{
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Issue",
|
||||
"date" : "2018-01-01",
|
||||
"to_shareholder" : "SH-00001",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 1,
|
||||
"to_no" : 500,
|
||||
"no_of_shares" : 500,
|
||||
"rate" : 10,
|
||||
"company" : "_Test Company"
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Issue",
|
||||
"date" : "2018-01-01",
|
||||
"to_shareholder" : "SH-00001",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 1,
|
||||
"to_no" : 500,
|
||||
"no_of_shares" : 500,
|
||||
"rate" : 10,
|
||||
"company" : "_Test Company",
|
||||
"asset_account" : "Cash - _TC",
|
||||
"equity_or_liability_account": "Creditors - _TC"
|
||||
},
|
||||
{
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Transfer",
|
||||
"date" : "2018-01-02",
|
||||
"from_shareholder" : "SH-00001",
|
||||
"to_shareholder" : "SH-00002",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 101,
|
||||
"to_no" : 200,
|
||||
"no_of_shares" : 100,
|
||||
"rate" : 15,
|
||||
"company" : "_Test Company"
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Transfer",
|
||||
"date" : "2018-01-02",
|
||||
"from_shareholder" : "SH-00001",
|
||||
"to_shareholder" : "SH-00002",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 101,
|
||||
"to_no" : 200,
|
||||
"no_of_shares" : 100,
|
||||
"rate" : 15,
|
||||
"company" : "_Test Company",
|
||||
"equity_or_liability_account": "Creditors - _TC"
|
||||
},
|
||||
{
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Transfer",
|
||||
"date" : "2018-01-03",
|
||||
"from_shareholder" : "SH-00001",
|
||||
"to_shareholder" : "SH-00003",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 201,
|
||||
"to_no" : 500,
|
||||
"no_of_shares" : 300,
|
||||
"rate" : 20,
|
||||
"company" : "_Test Company"
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Transfer",
|
||||
"date" : "2018-01-03",
|
||||
"from_shareholder" : "SH-00001",
|
||||
"to_shareholder" : "SH-00003",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 201,
|
||||
"to_no" : 500,
|
||||
"no_of_shares" : 300,
|
||||
"rate" : 20,
|
||||
"company" : "_Test Company",
|
||||
"equity_or_liability_account": "Creditors - _TC"
|
||||
},
|
||||
{
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Transfer",
|
||||
"date" : "2018-01-04",
|
||||
"from_shareholder" : "SH-00003",
|
||||
"to_shareholder" : "SH-00002",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 201,
|
||||
"to_no" : 400,
|
||||
"no_of_shares" : 200,
|
||||
"rate" : 15,
|
||||
"company" : "_Test Company"
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Transfer",
|
||||
"date" : "2018-01-04",
|
||||
"from_shareholder" : "SH-00003",
|
||||
"to_shareholder" : "SH-00002",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 201,
|
||||
"to_no" : 400,
|
||||
"no_of_shares" : 200,
|
||||
"rate" : 15,
|
||||
"company" : "_Test Company",
|
||||
"equity_or_liability_account": "Creditors - _TC"
|
||||
},
|
||||
{
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Purchase",
|
||||
"date" : "2018-01-05",
|
||||
"from_shareholder" : "SH-00003",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 401,
|
||||
"to_no" : 500,
|
||||
"no_of_shares" : 100,
|
||||
"rate" : 25,
|
||||
"company" : "_Test Company"
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Purchase",
|
||||
"date" : "2018-01-05",
|
||||
"from_shareholder" : "SH-00003",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 401,
|
||||
"to_no" : 500,
|
||||
"no_of_shares" : 100,
|
||||
"rate" : 25,
|
||||
"company" : "_Test Company",
|
||||
"asset_account" : "Cash - _TC",
|
||||
"equity_or_liability_account": "Creditors - _TC"
|
||||
}
|
||||
]
|
||||
for d in share_transfers:
|
||||
@ -84,30 +91,33 @@ class TestShareTransfer(unittest.TestCase):
|
||||
|
||||
def test_invalid_share_transfer(self):
|
||||
doc = frappe.get_doc({
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Transfer",
|
||||
"date" : "2018-01-05",
|
||||
"from_shareholder" : "SH-00003",
|
||||
"to_shareholder" : "SH-00002",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 1,
|
||||
"to_no" : 100,
|
||||
"no_of_shares" : 100,
|
||||
"rate" : 15,
|
||||
"company" : "_Test Company"
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Transfer",
|
||||
"date" : "2018-01-05",
|
||||
"from_shareholder" : "SH-00003",
|
||||
"to_shareholder" : "SH-00002",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 1,
|
||||
"to_no" : 100,
|
||||
"no_of_shares" : 100,
|
||||
"rate" : 15,
|
||||
"company" : "_Test Company",
|
||||
"equity_or_liability_account": "Creditors - _TC"
|
||||
})
|
||||
self.assertRaises(ShareDontExists, doc.insert)
|
||||
|
||||
doc = frappe.get_doc({
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Purchase",
|
||||
"date" : "2018-01-02",
|
||||
"from_shareholder" : "SH-00001",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 1,
|
||||
"to_no" : 200,
|
||||
"no_of_shares" : 200,
|
||||
"rate" : 15,
|
||||
"company" : "_Test Company"
|
||||
"doctype" : "Share Transfer",
|
||||
"transfer_type" : "Purchase",
|
||||
"date" : "2018-01-02",
|
||||
"from_shareholder" : "SH-00001",
|
||||
"share_type" : "Equity",
|
||||
"from_no" : 1,
|
||||
"to_no" : 200,
|
||||
"no_of_shares" : 200,
|
||||
"rate" : 15,
|
||||
"company" : "_Test Company",
|
||||
"asset_account" : "Cash - _TC",
|
||||
"equity_or_liability_account": "Creditors - _TC"
|
||||
})
|
||||
self.assertRaises(ShareDontExists, doc.insert)
|
||||
|
@ -1624,7 +1624,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
setTimeout(function () {
|
||||
w.print();
|
||||
w.close();
|
||||
}, 1000)
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
submit_invoice: function () {
|
||||
@ -1681,6 +1681,12 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
$(this.wrapper).find('.pos-bill').css('pointer-events', pointer_events);
|
||||
$(this.wrapper).find('.pos-items-section').css('pointer-events', pointer_events);
|
||||
this.set_primary_action();
|
||||
|
||||
$(this.wrapper).find('#pos-item-disc').prop('disabled',
|
||||
this.pos_profile_data.allow_user_to_edit_discount ? false : true);
|
||||
|
||||
$(this.wrapper).find('#pos-item-price').prop('disabled',
|
||||
this.pos_profile_data.allow_user_to_edit_rate ? false : true);
|
||||
},
|
||||
|
||||
create_invoice: function () {
|
||||
@ -1691,20 +1697,13 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
if(this.si_docs) {
|
||||
this.si_docs.forEach((row) => {
|
||||
existing_pos_list.push(Object.keys(row));
|
||||
existing_pos_list.push(Object.keys(row)[0]);
|
||||
});
|
||||
}
|
||||
|
||||
if (this.frm.doc.offline_pos_name
|
||||
&& in_list(existing_pos_list, this.frm.doc.offline_pos_name)) {
|
||||
&& in_list(existing_pos_list, cstr(this.frm.doc.offline_pos_name))) {
|
||||
this.update_invoice()
|
||||
//to retrieve and set the default payment
|
||||
invoice_data[this.frm.doc.offline_pos_name] = this.frm.doc;
|
||||
invoice_data[this.frm.doc.offline_pos_name].payments[0].amount = this.frm.doc.net_total
|
||||
invoice_data[this.frm.doc.offline_pos_name].payments[0].base_amount = this.frm.doc.net_total
|
||||
|
||||
this.frm.doc.paid_amount = this.frm.doc.net_total
|
||||
this.frm.doc.outstanding_amount = 0
|
||||
} else if(!this.frm.doc.offline_pos_name) {
|
||||
this.frm.doc.offline_pos_name = frappe.datetime.now_datetime();
|
||||
this.frm.doc.posting_date = frappe.datetime.get_today();
|
||||
@ -1898,7 +1897,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
serial_no = me.item_serial_no[key][0];
|
||||
}
|
||||
|
||||
if (this.items[0].has_serial_no && serial_no == "") {
|
||||
if (this.items && this.items[0].has_serial_no && serial_no == "") {
|
||||
this.refresh();
|
||||
frappe.throw(__(repl("Error: Serial no is mandatory for item %(item)s", {
|
||||
'item': this.items[0].item_code
|
||||
|
@ -40,6 +40,11 @@ def get_data():
|
||||
"type": "doctype",
|
||||
"name": "Plaid Settings",
|
||||
"description": _("Connect your bank accounts to ERPNext"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Exotel Settings",
|
||||
"description": _("Connect your Exotel Account to ERPNext and track call logs"),
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -3,30 +3,31 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
import requests
|
||||
from frappe.utils.password import get_decrypted_password
|
||||
from plaid import Client
|
||||
from plaid.errors import APIError, ItemError
|
||||
|
||||
import frappe
|
||||
import requests
|
||||
|
||||
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"))
|
||||
plaid_settings = frappe.get_single("Plaid Settings")
|
||||
|
||||
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")
|
||||
"plaid_client_id": plaid_settings.plaid_client_id,
|
||||
"plaid_secret": get_decrypted_password("Plaid Settings", "Plaid Settings", 'plaid_secret'),
|
||||
"plaid_public_key": plaid_settings.plaid_public_key,
|
||||
"plaid_env": plaid_settings.plaid_env
|
||||
}
|
||||
|
||||
self.client = Client(client_id=self.config["plaid_client_id"],
|
||||
secret=self.config["plaid_secret"],
|
||||
public_key=self.config["plaid_public_key"],
|
||||
environment=self.config["plaid_env"]
|
||||
)
|
||||
self.client = Client(client_id=self.config.get("plaid_client_id"),
|
||||
secret=self.config.get("plaid_secret"),
|
||||
public_key=self.config.get("plaid_public_key"),
|
||||
environment=self.config.get("plaid_env")
|
||||
)
|
||||
|
||||
self.access_token = access_token
|
||||
|
||||
@ -78,4 +79,4 @@ class PlaidConnector():
|
||||
transactions.extend(response['transactions'])
|
||||
return transactions
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
|
||||
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
|
||||
|
@ -4,8 +4,18 @@
|
||||
frappe.provide("erpnext.integrations");
|
||||
|
||||
frappe.ui.form.on('Plaid Settings', {
|
||||
link_new_account: function(frm) {
|
||||
new erpnext.integrations.plaidLink(frm);
|
||||
enabled: function(frm) {
|
||||
frm.toggle_reqd('plaid_client_id', frm.doc.enabled);
|
||||
frm.toggle_reqd('plaid_secret', frm.doc.enabled);
|
||||
frm.toggle_reqd('plaid_public_key', frm.doc.enabled);
|
||||
frm.toggle_reqd('plaid_env', frm.doc.enabled);
|
||||
},
|
||||
refresh: function(frm) {
|
||||
if(frm.doc.enabled) {
|
||||
frm.add_custom_button('Link a new bank account', () => {
|
||||
new erpnext.integrations.plaidLink(frm);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -19,20 +29,10 @@ erpnext.integrations.plaidLink = class plaidLink {
|
||||
|
||||
init_config() {
|
||||
const me = this;
|
||||
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.plaid_configuration')
|
||||
.then(result => {
|
||||
if (result !== "disabled") {
|
||||
if (result.plaid_env == undefined || result.plaid_public_key == undefined) {
|
||||
frappe.throw(__("Please add valid Plaid api keys in site_config.json first"));
|
||||
}
|
||||
me.plaid_env = result.plaid_env;
|
||||
me.plaid_public_key = result.plaid_public_key;
|
||||
me.client_name = result.client_name;
|
||||
me.init_plaid();
|
||||
} else {
|
||||
frappe.throw(__("Please save your document before adding a new account"));
|
||||
}
|
||||
});
|
||||
me.plaid_env = me.frm.doc.plaid_env;
|
||||
me.plaid_public_key = me.frm.doc.plaid_public_key;
|
||||
me.client_name = frappe.boot.sitename;
|
||||
me.init_plaid();
|
||||
}
|
||||
|
||||
init_plaid() {
|
||||
@ -104,4 +104,4 @@ erpnext.integrations.plaidLink = class plaidLink {
|
||||
});
|
||||
}, __("Select a company"), __("Continue"));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -1,161 +1,96 @@
|
||||
{
|
||||
"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",
|
||||
"creation": "2018-10-25 10:02:48.656165",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"enabled",
|
||||
"column_break_2",
|
||||
"automatic_sync",
|
||||
"section_break_4",
|
||||
"plaid_client_id",
|
||||
"plaid_secret",
|
||||
"column_break_7",
|
||||
"plaid_public_key",
|
||||
"plaid_env"
|
||||
],
|
||||
"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
|
||||
},
|
||||
"default": "0",
|
||||
"fieldname": "enabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"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": "automatic_sync",
|
||||
"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": "Synchronize all accounts every hour",
|
||||
"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
|
||||
},
|
||||
"default": "0",
|
||||
"depends_on": "eval:doc.enabled==1",
|
||||
"fieldname": "automatic_sync",
|
||||
"fieldtype": "Check",
|
||||
"label": "Synchronize all accounts every hour"
|
||||
},
|
||||
{
|
||||
"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)&&(!doc.__islocal)",
|
||||
"fieldname": "link_new_account",
|
||||
"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": "Link a new bank 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
|
||||
"depends_on": "eval:doc.enabled==1",
|
||||
"fieldname": "plaid_client_id",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Plaid Client ID",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.enabled==1",
|
||||
"fieldname": "plaid_secret",
|
||||
"fieldtype": "Password",
|
||||
"in_list_view": 1,
|
||||
"label": "Plaid Secret",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.enabled==1",
|
||||
"fieldname": "plaid_public_key",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Plaid Public Key",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.enabled==1",
|
||||
"fieldname": "plaid_env",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Plaid Environment",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"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-12-14 12:51:12.331395",
|
||||
"modified_by": "Administrator",
|
||||
"module": "ERPNext Integrations",
|
||||
"name": "Plaid Settings",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"issingle": 1,
|
||||
"modified": "2019-08-13 17:00:06.939422",
|
||||
"modified_by": "Administrator",
|
||||
"module": "ERPNext Integrations",
|
||||
"name": "Plaid Settings",
|
||||
"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,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"role": "System Manager",
|
||||
"share": 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
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -16,8 +16,13 @@ class PlaidSettings(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
def plaid_configuration():
|
||||
if frappe.db.get_value("Plaid Settings", None, "enabled") == "1":
|
||||
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 }
|
||||
if frappe.db.get_single_value("Plaid Settings", "enabled"):
|
||||
plaid_settings = frappe.get_single("Plaid Settings")
|
||||
return {
|
||||
"plaid_public_key": plaid_settings.plaid_public_key,
|
||||
"plaid_env": plaid_settings.plaid_env,
|
||||
"client_name": frappe.local.site
|
||||
}
|
||||
else:
|
||||
return "disabled"
|
||||
|
||||
|
@ -171,6 +171,8 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "user_id.user_image",
|
||||
"fetch_if_empty": 1,
|
||||
"fieldname": "image",
|
||||
"fieldtype": "Attach Image",
|
||||
"hidden": 1,
|
||||
@ -780,7 +782,7 @@
|
||||
"icon": "fa fa-user",
|
||||
"idx": 24,
|
||||
"image_field": "image",
|
||||
"modified": "2019-09-06 15:54:36.735147",
|
||||
"modified": "2019-09-12 14:21:12.711280",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee",
|
||||
|
@ -8,6 +8,8 @@ from frappe.utils import flt
|
||||
from erpnext.hr.doctype.leave_application.leave_application \
|
||||
import get_leave_balance_on, get_leaves_for_period
|
||||
|
||||
from erpnext.hr.report.employee_leave_balance_summary.employee_leave_balance_summary \
|
||||
import get_department_leave_approver_map
|
||||
|
||||
def execute(filters=None):
|
||||
leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc")
|
||||
@ -19,7 +21,7 @@ def execute(filters=None):
|
||||
|
||||
def get_columns(leave_types):
|
||||
columns = [
|
||||
_("Employee") + ":Link/Employee:150",
|
||||
_("Employee") + ":Link.Employee:150",
|
||||
_("Employee Name") + "::200",
|
||||
_("Department") +"::150"
|
||||
]
|
||||
@ -52,11 +54,13 @@ def get_data(filters, leave_types):
|
||||
|
||||
active_employees = frappe.get_all("Employee",
|
||||
filters=conditions,
|
||||
fields=["name", "employee_name", "department", "user_id"])
|
||||
fields=["name", "employee_name", "department", "user_id", "leave_approver"])
|
||||
|
||||
department_approver_map = get_department_leave_approver_map(filters.get('department'))
|
||||
|
||||
data = []
|
||||
for employee in active_employees:
|
||||
leave_approvers = get_approvers(employee.department)
|
||||
leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
|
||||
if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) or ("HR Manager" in frappe.get_roles(user)):
|
||||
row = [employee.name, employee.employee_name, employee.department]
|
||||
|
||||
@ -66,46 +70,13 @@ def get_data(filters, leave_types):
|
||||
filters.from_date, filters.to_date) * -1
|
||||
|
||||
# opening balance
|
||||
opening = get_total_allocated_leaves(employee.name, leave_type, filters.from_date, filters.to_date)
|
||||
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
|
||||
|
||||
# closing balance
|
||||
closing = flt(opening) - flt(leaves_taken)
|
||||
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
|
||||
|
||||
row += [opening, leaves_taken, closing]
|
||||
|
||||
data.append(row)
|
||||
|
||||
return data
|
||||
|
||||
def get_approvers(department):
|
||||
if not department:
|
||||
return []
|
||||
|
||||
approvers = []
|
||||
# get current department and all its child
|
||||
department_details = frappe.db.get_value("Department", {"name": department}, ["lft", "rgt"], as_dict=True)
|
||||
department_list = frappe.db.sql("""select name from `tabDepartment`
|
||||
where lft >= %s and rgt <= %s order by lft desc
|
||||
""", (department_details.lft, department_details.rgt), as_list = True)
|
||||
|
||||
# retrieve approvers list from current department and from its subsequent child departments
|
||||
for d in department_list:
|
||||
approvers.extend([l.leave_approver for l in frappe.db.sql("""select approver from `tabDepartment Approver` \
|
||||
where parent = %s and parentfield = 'leave_approvers'""", (d), as_dict=True)])
|
||||
|
||||
return approvers
|
||||
|
||||
def get_total_allocated_leaves(employee, leave_type, from_date, to_date):
|
||||
''' Returns leave allocation between from date and to date '''
|
||||
leave_allocation_records = frappe.db.get_all('Leave Ledger Entry', filters={
|
||||
'docstatus': 1,
|
||||
'is_expired': 0,
|
||||
'leave_type': leave_type,
|
||||
'employee': employee,
|
||||
'transaction_type': 'Leave Allocation'
|
||||
}, or_filters={
|
||||
'from_date': ['between', (from_date, to_date)],
|
||||
'to_date': ['between', (from_date, to_date)]
|
||||
}, fields=['SUM(leaves) as leaves'])
|
||||
|
||||
return flt(leave_allocation_records[0].get('leaves')) if leave_allocation_records else flt(0)
|
||||
return data
|
@ -4,6 +4,20 @@
|
||||
|
||||
frappe.query_reports['Employee Leave Balance Summary'] = {
|
||||
filters: [
|
||||
{
|
||||
fieldname:'from_date',
|
||||
label: __('From Date'),
|
||||
fieldtype: 'Date',
|
||||
reqd: 1,
|
||||
default: frappe.defaults.get_default('year_start_date')
|
||||
},
|
||||
{
|
||||
fieldname:'to_date',
|
||||
label: __('To Date'),
|
||||
fieldtype: 'Date',
|
||||
reqd: 1,
|
||||
default: frappe.defaults.get_default('year_end_date')
|
||||
},
|
||||
{
|
||||
fieldname:'company',
|
||||
label: __('Company'),
|
||||
@ -19,18 +33,10 @@ frappe.query_reports['Employee Leave Balance Summary'] = {
|
||||
options: 'Employee',
|
||||
},
|
||||
{
|
||||
fieldname:'from_date',
|
||||
label: __('From Date'),
|
||||
fieldtype: 'Date',
|
||||
reqd: 1,
|
||||
default: frappe.defaults.get_default('year_start_date')
|
||||
},
|
||||
{
|
||||
fieldname:'to_date',
|
||||
label: __('To Date'),
|
||||
fieldtype: 'Date',
|
||||
reqd: 1,
|
||||
default: frappe.defaults.get_default('year_end_date')
|
||||
fieldname:'department',
|
||||
label: __('Department'),
|
||||
fieldtype: 'Link',
|
||||
options: 'Department',
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -5,9 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import flt
|
||||
from frappe import _
|
||||
from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period
|
||||
|
||||
from erpnext.hr.report.employee_leave_balance.employee_leave_balance import get_total_allocated_leaves
|
||||
from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period, get_leave_balance_on
|
||||
|
||||
def execute(filters=None):
|
||||
if filters.to_date <= filters.from_date:
|
||||
@ -58,16 +56,14 @@ def get_columns():
|
||||
def get_data(filters):
|
||||
leave_types = frappe.db.sql_list("SELECT `name` FROM `tabLeave Type` ORDER BY `name` ASC")
|
||||
|
||||
conditions = {
|
||||
'status': 'Active',
|
||||
}
|
||||
conditions = get_conditions(filters)
|
||||
|
||||
if filters.get('employee'):
|
||||
conditions['name'] = filters.get('employee')
|
||||
user = frappe.session.user
|
||||
department_approver_map = get_department_leave_approver_map(filters.get('department'))
|
||||
|
||||
active_employees = frappe.get_all('Employee',
|
||||
active_employees = frappe.get_list('Employee',
|
||||
filters=conditions,
|
||||
fields=['name', 'employee_name', 'department', 'user_id'])
|
||||
fields=['name', 'employee_name', 'department', 'user_id', 'leave_approver'])
|
||||
|
||||
data = []
|
||||
|
||||
@ -76,21 +72,59 @@ def get_data(filters):
|
||||
'leave_type': leave_type
|
||||
})
|
||||
for employee in active_employees:
|
||||
row = frappe._dict({
|
||||
'employee': employee.name,
|
||||
'employee_name': employee.employee_name
|
||||
})
|
||||
|
||||
leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
|
||||
|
||||
leaves_taken = get_leaves_for_period(employee.name, leave_type,
|
||||
filters.from_date, filters.to_date) * -1
|
||||
if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) \
|
||||
or ("HR Manager" in frappe.get_roles(user)):
|
||||
row = frappe._dict({
|
||||
'employee': employee.name,
|
||||
'employee_name': employee.employee_name
|
||||
})
|
||||
|
||||
opening = get_total_allocated_leaves(employee.name, leave_type, filters.from_date, filters.to_date)
|
||||
closing = flt(opening) - flt(leaves_taken)
|
||||
leaves_taken = get_leaves_for_period(employee.name, leave_type,
|
||||
filters.from_date, filters.to_date) * -1
|
||||
|
||||
row.opening_balance = opening
|
||||
row.leaves_taken = leaves_taken
|
||||
row.closing_balance = closing
|
||||
row.indent = 1
|
||||
data.append(row)
|
||||
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
|
||||
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
|
||||
|
||||
row.opening_balance = opening
|
||||
row.leaves_taken = leaves_taken
|
||||
row.closing_balance = closing
|
||||
row.indent = 1
|
||||
data.append(row)
|
||||
|
||||
return data
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions={
|
||||
'status': 'Active',
|
||||
}
|
||||
if filters.get('employee'):
|
||||
conditions['name'] = filters.get('employee')
|
||||
|
||||
if filters.get('employee'):
|
||||
conditions['name'] = filters.get('employee')
|
||||
|
||||
return conditions
|
||||
|
||||
def get_department_leave_approver_map(department=None):
|
||||
conditions=''
|
||||
if department:
|
||||
conditions='and department_name = %(department)s or parent_department = %(department)s'%{'department': department}
|
||||
|
||||
# get current department and all its child
|
||||
department_list = frappe.db.sql_list(''' SELECT name FROM `tabDepartment` WHERE disabled=0 {0}'''.format(conditions)) #nosec
|
||||
|
||||
# retrieve approvers list from current department and from its subsequent child departments
|
||||
approver_list = frappe.get_all('Department Approver', filters={
|
||||
'parentfield': 'leave_approvers',
|
||||
'parent': ('in', department_list)
|
||||
}, fields=['parent', 'approver'], as_list=1)
|
||||
|
||||
approvers = {}
|
||||
|
||||
for k, v in approver_list:
|
||||
approvers.setdefault(k, []).append(v)
|
||||
|
||||
return approvers
|
||||
|
@ -625,6 +625,7 @@ erpnext.patches.v12_0.add_default_buying_selling_terms_in_company
|
||||
erpnext.patches.v12_0.update_ewaybill_field_position
|
||||
erpnext.patches.v12_0.create_accounting_dimensions_in_missing_doctypes
|
||||
erpnext.patches.v11_1.set_status_for_material_request_type_manufacture
|
||||
erpnext.patches.v12_0.move_plaid_settings_to_doctype
|
||||
execute:frappe.reload_doc('desk', 'doctype','dashboard_chart_link')
|
||||
execute:frappe.reload_doc('desk', 'doctype','dashboard')
|
||||
execute:frappe.reload_doc('desk', 'doctype','dashboard_chart_source')
|
||||
|
22
erpnext/patches/v12_0/move_plaid_settings_to_doctype.py
Normal file
22
erpnext/patches/v12_0/move_plaid_settings_to_doctype.py
Normal file
@ -0,0 +1,22 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("erpnext_integrations", "doctype", "plaid_settings")
|
||||
plaid_settings = frappe.get_single("Plaid Settings")
|
||||
if plaid_settings.enabled:
|
||||
if not (frappe.conf.plaid_client_id and frappe.conf.plaid_env \
|
||||
and frappe.conf.plaid_public_key and frappe.conf.plaid_secret):
|
||||
plaid_settings.enabled = 0
|
||||
else:
|
||||
plaid_settings.update({
|
||||
"plaid_client_id": frappe.conf.plaid_client_id,
|
||||
"plaid_public_key": frappe.conf.plaid_public_key,
|
||||
"plaid_env": frappe.conf.plaid_env,
|
||||
"plaid_secret": frappe.conf.plaid_secret
|
||||
})
|
||||
plaid_settings.flags.ignore_mandatory = True
|
||||
plaid_settings.save()
|
@ -9,7 +9,7 @@ import frappe
|
||||
from frappe import _, throw
|
||||
from frappe.utils import add_days, cstr, date_diff, get_link_to_form, getdate
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
|
||||
from frappe.desk.form.assign_to import close_all_assignments, clear
|
||||
|
||||
class CircularReferenceError(frappe.ValidationError): pass
|
||||
class EndDateCannotBeGreaterThanProjectEndDateError(frappe.ValidationError): pass
|
||||
@ -45,8 +45,7 @@ class Task(NestedSet):
|
||||
if frappe.db.get_value("Task", d.task, "status") != "Completed":
|
||||
frappe.throw(_("Cannot close task {0} as its dependant task {1} is not closed.").format(frappe.bold(self.name), frappe.bold(d.task)))
|
||||
|
||||
from frappe.desk.form.assign_to import clear
|
||||
clear(self.doctype, self.name)
|
||||
close_all_assignments(self.doctype, self.name)
|
||||
|
||||
def validate_progress(self):
|
||||
if (self.progress or 0) > 100:
|
||||
@ -77,8 +76,9 @@ class Task(NestedSet):
|
||||
self.populate_depends_on()
|
||||
|
||||
def unassign_todo(self):
|
||||
if self.status in ("Completed", "Cancelled"):
|
||||
from frappe.desk.form.assign_to import clear
|
||||
if self.status == "Completed":
|
||||
close_all_assignments(self.doctype, self.name)
|
||||
if self.status == "Cancelled":
|
||||
clear(self.doctype, self.name)
|
||||
|
||||
def update_total_expense_claim(self):
|
||||
|
@ -28,12 +28,12 @@ class CallPopup {
|
||||
'depends_on': () => this.call_log.lead
|
||||
}, {
|
||||
'fieldtype': 'Button',
|
||||
'label': __('Make New Contact'),
|
||||
'label': __('Create New Contact'),
|
||||
'click': () => frappe.new_doc('Contact', { 'mobile_no': this.caller_number }),
|
||||
'depends_on': () => !this.get_caller_name()
|
||||
}, {
|
||||
'fieldtype': 'Button',
|
||||
'label': __('Make New Lead'),
|
||||
'label': __('Create New Lead'),
|
||||
'click': () => frappe.new_doc('Lead', { 'mobile_no': this.caller_number }),
|
||||
'depends_on': () => !this.get_caller_name()
|
||||
}, {
|
||||
|
@ -722,7 +722,7 @@ def get_company_gstin_number(company):
|
||||
if gstin:
|
||||
return gstin[0]["gstin"]
|
||||
else:
|
||||
frappe.throw(_("No GST No. found for the Company."))
|
||||
frappe.throw(_("Please set valid GSTIN No. in Company Address"))
|
||||
|
||||
def download_json_file(filename, report_type, data):
|
||||
''' download json content in a file '''
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -151,7 +151,7 @@ class NamingSeries(Document):
|
||||
|
||||
def insert_series(self, series):
|
||||
"""insert series if missing"""
|
||||
if not frappe.db.get_value('Series', series, 'name', order_by="name"):
|
||||
if frappe.db.get_value('Series', series, 'name', order_by="name") == None:
|
||||
frappe.db.sql("insert into tabSeries (name, current) values (%s, 0)", (series))
|
||||
|
||||
def update_series_start(self):
|
||||
|
@ -1173,7 +1173,7 @@ class StockEntry(StockController):
|
||||
frappe.db.sql("""UPDATE `tabPurchase Order Item Supplied` pos
|
||||
SET pos.supplied_qty = (SELECT ifnull(sum(transfer_qty), 0) FROM `tabStock Entry Detail` sed
|
||||
WHERE pos.name = sed.po_detail and sed.docstatus = 1)
|
||||
WHERE pos.docstatus = 1""")
|
||||
WHERE pos.docstatus = 1 and pos.parent = %s""", self.purchase_order)
|
||||
|
||||
#Update reserved sub contracted quantity in bin based on Supplied Item Details and
|
||||
for d in self.get("items"):
|
||||
|
Loading…
x
Reference in New Issue
Block a user