Compare commits
226 Commits
v11.0.3
...
v11.0.3-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
881bb4646b | ||
|
|
4293d17602 | ||
|
|
ca66c7ba14 | ||
|
|
83fd31973f | ||
|
|
ac64b39562 | ||
|
|
c73c576536 | ||
|
|
669c5d0298 | ||
|
|
d3e3c1ba72 | ||
|
|
55416e08f1 | ||
|
|
1b105e2575 | ||
|
|
60d8a0da1e | ||
|
|
9db75ecde2 | ||
|
|
635d4dbebe | ||
|
|
cf076f4692 | ||
|
|
034429b34d | ||
|
|
a0e533ede5 | ||
|
|
874866e9f9 | ||
|
|
c365ce8f21 | ||
|
|
3a11f34355 | ||
|
|
91eac5a7cf | ||
|
|
aef7a6ec44 | ||
|
|
ac6e3a69f9 | ||
|
|
473437931c | ||
|
|
4215b85e46 | ||
|
|
7e97230c92 | ||
|
|
bbfdc13ab7 | ||
|
|
6192d24235 | ||
|
|
24fe7286fc | ||
|
|
5d1171678e | ||
|
|
b4cf72c770 | ||
|
|
3c9155e406 | ||
|
|
25edac451d | ||
|
|
25e9db5e81 | ||
|
|
500ddc94c7 | ||
|
|
7a7615ed66 | ||
|
|
007fbfbfb7 | ||
|
|
e2afbb7abe | ||
|
|
961b7dee9d | ||
|
|
a7a32d7400 | ||
|
|
77b60928bf | ||
|
|
bbd8b04012 | ||
|
|
bb1b6b42e2 | ||
|
|
4fdbff7456 | ||
|
|
0cbb9b54fa | ||
|
|
8e71074e1c | ||
|
|
e45868a3c6 | ||
|
|
ff0deedca9 | ||
|
|
22731e39ba | ||
|
|
bfb88f7839 | ||
|
|
82660913a5 | ||
|
|
8aca56836b | ||
|
|
19be730b9c | ||
|
|
a5a926967b | ||
|
|
666e6e665b | ||
|
|
4bb90add1d | ||
|
|
44ec05f79b | ||
|
|
615571dd21 | ||
|
|
7844b79274 | ||
|
|
7c443264a4 | ||
|
|
10dfd4a48f | ||
|
|
3185b37360 | ||
|
|
8d0195246d | ||
|
|
4fa58359c8 | ||
|
|
102eb998ac | ||
|
|
3c29967d27 | ||
|
|
ea75295bb3 | ||
|
|
d2c643eb0b | ||
|
|
94fcb0e9f9 | ||
|
|
2a966f26af | ||
|
|
741bd29b74 | ||
|
|
0d2a4c6a59 | ||
|
|
42510a411f | ||
|
|
3362d6b948 | ||
|
|
8c62ab4af0 | ||
|
|
314c97cbf1 | ||
|
|
a16f0f4423 | ||
|
|
64b6421fce | ||
|
|
6c743bebf2 | ||
|
|
50447b195d | ||
|
|
e9890a3ec8 | ||
|
|
4833b4c274 | ||
|
|
a398d6bf4f | ||
|
|
dc279ded15 | ||
|
|
d791af8331 | ||
|
|
b1241caf48 | ||
|
|
b6a735e021 | ||
|
|
785f1aa96d | ||
|
|
2291323c65 | ||
|
|
1cb1074f6b | ||
|
|
d92f3ac480 | ||
|
|
dd87e0f1e2 | ||
|
|
4cfff7829b | ||
|
|
3855156b7d | ||
|
|
14c6ab0ee9 | ||
|
|
6a8957b430 | ||
|
|
62592d3c44 | ||
|
|
fd9c451909 | ||
|
|
d1fbaf8f32 | ||
|
|
275ef826a4 | ||
|
|
8b1133cb24 | ||
|
|
d080a17961 | ||
|
|
e64dcfc2f9 | ||
|
|
e895845ae1 | ||
|
|
523f77e82b | ||
|
|
dcf7401104 | ||
|
|
143d4da901 | ||
|
|
c24d2fdf6c | ||
|
|
a259466643 | ||
|
|
0309bbee30 | ||
|
|
796bffbee1 | ||
|
|
4c07970545 | ||
|
|
fa7c8a9f8b | ||
|
|
99c064305f | ||
|
|
75c1682e61 | ||
|
|
2dc8972794 | ||
|
|
f786eccdf9 | ||
|
|
a1036ad50b | ||
|
|
8a4bcefec4 | ||
|
|
5b34d00bc0 | ||
|
|
d2c5b50842 | ||
|
|
cf91f34ffa | ||
|
|
563b1d153b | ||
|
|
ecba14e6cf | ||
|
|
ee3b788024 | ||
|
|
b509b06edf | ||
|
|
87441bf62e | ||
|
|
5fcccda883 | ||
|
|
4fb9230d16 | ||
|
|
95d93913ce | ||
|
|
37d3686372 | ||
|
|
8cafb5fbbb | ||
|
|
0bd254b02b | ||
|
|
5e466bace4 | ||
|
|
c2857fd2cc | ||
|
|
063cf9c582 | ||
|
|
36be62b927 | ||
|
|
cfdd629fd7 | ||
|
|
272956980d | ||
|
|
f7b5b7beb4 | ||
|
|
39903647ae | ||
|
|
cd9be8f0a6 | ||
|
|
5615cb4735 | ||
|
|
e7e269d4a4 | ||
|
|
b8c1897a80 | ||
|
|
58a080a1b1 | ||
|
|
29fe8ce114 | ||
|
|
538678afc4 | ||
|
|
ad908779be | ||
|
|
5eafa5a487 | ||
|
|
97dbb4d125 | ||
|
|
5cff01634e | ||
|
|
32206029ac | ||
|
|
deb9f0e03c | ||
|
|
db5ffce742 | ||
|
|
0d7bd43367 | ||
|
|
2123b97d31 | ||
|
|
4f5214a136 | ||
|
|
00a16a9337 | ||
|
|
17ac38ff29 | ||
|
|
be6e426fe0 | ||
|
|
dc2bab2b72 | ||
|
|
4c61861163 | ||
|
|
4faea037bb | ||
|
|
c4ebbd1322 | ||
|
|
2291558c5f | ||
|
|
d69dc954c7 | ||
|
|
c6eac7c60b | ||
|
|
5ae344593e | ||
|
|
6dc4cdca3a | ||
|
|
18678696db | ||
|
|
7d929c508f | ||
|
|
65652071ff | ||
|
|
79dc8ac9cc | ||
|
|
8b42bf57cd | ||
|
|
9f2859701e | ||
|
|
b13b9b4ed3 | ||
|
|
897d1baf74 | ||
|
|
6e3b1a58a1 | ||
|
|
f9930ff2a4 | ||
|
|
3204c94fdd | ||
|
|
cbb112f2db | ||
|
|
15e7646edd | ||
|
|
8bf9f377dd | ||
|
|
d1b87ba41c | ||
|
|
d6cacbe565 | ||
|
|
210f4984f7 | ||
|
|
75fa6b3ee8 | ||
|
|
efd776da46 | ||
|
|
a5576f5b21 | ||
|
|
719701f2a4 | ||
|
|
7d115183e4 | ||
|
|
3b11debcd2 | ||
|
|
b2281cc1fd | ||
|
|
5a2aced586 | ||
|
|
11e2119670 | ||
|
|
6a5e6ed2ff | ||
|
|
9e67b8ec4d | ||
|
|
622bd10946 | ||
|
|
8976ad5ca1 | ||
|
|
c7f8b82fff | ||
|
|
6b62b86bbf | ||
|
|
8fbf856618 | ||
|
|
90cf2ddc01 | ||
|
|
6ecb2556b7 | ||
|
|
4fd7a4e0d7 | ||
|
|
e4c9ac3961 | ||
|
|
90f9f9d3d8 | ||
|
|
6575e52942 | ||
|
|
1cf71d96b1 | ||
|
|
ea0ef95539 | ||
|
|
c2dd9ab778 | ||
|
|
0fc4917d81 | ||
|
|
5c335550e3 | ||
|
|
7d6d678e8d | ||
|
|
c22ba2ec26 | ||
|
|
183972f58f | ||
|
|
1e7c32b909 | ||
|
|
c3772f1ac4 | ||
|
|
e20b7cc47d | ||
|
|
352e6494f3 | ||
|
|
0cf0ebf08b | ||
|
|
a7ae06eadb | ||
|
|
90197dd341 | ||
|
|
41d1982b90 | ||
|
|
12ec142a69 | ||
|
|
423549e084 |
@@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '10.1.54'
|
||||
__version__ = '10.1.63'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -35,8 +35,8 @@ def validate_service_stop_date(doc):
|
||||
def convert_deferred_expense_to_expense(start_date=None, end_date=None):
|
||||
# check for the purchase invoice for which GL entries has to be done
|
||||
invoices = frappe.db.sql_list('''
|
||||
select parent from `tabPurchase Invoice Item` where service_start_date<=%s and service_end_date>=%s
|
||||
and enable_deferred_expense = 1 and docstatus = 1
|
||||
select distinct parent from `tabPurchase Invoice Item` where service_start_date<=%s and service_end_date>=%s
|
||||
and enable_deferred_expense = 1 and docstatus = 1 and ifnull(amount, 0) > 0
|
||||
''', (end_date or today(), start_date or add_months(today(), -1)))
|
||||
|
||||
# For each invoice, book deferred expense
|
||||
@@ -47,8 +47,8 @@ def convert_deferred_expense_to_expense(start_date=None, end_date=None):
|
||||
def convert_deferred_revenue_to_income(start_date=None, end_date=None):
|
||||
# check for the sales invoice for which GL entries has to be done
|
||||
invoices = frappe.db.sql_list('''
|
||||
select parent from `tabSales Invoice Item` where service_start_date<=%s and service_end_date>=%s
|
||||
and enable_deferred_revenue = 1 and docstatus = 1
|
||||
select distinct parent from `tabSales Invoice Item` where service_start_date<=%s and service_end_date>=%s
|
||||
and enable_deferred_revenue = 1 and docstatus = 1 and ifnull(amount, 0) > 0
|
||||
''', (end_date or today(), start_date or add_months(today(), -1)))
|
||||
|
||||
# For each invoice, book deferred revenue
|
||||
@@ -157,6 +157,7 @@ def book_deferred_income_or_expense(doc, start_date=None, end_date=None):
|
||||
"credit": base_amount,
|
||||
"credit_in_account_currency": amount,
|
||||
"cost_center": item.cost_center,
|
||||
"voucher_detail_no": item.name,
|
||||
'posting_date': booking_end_date,
|
||||
'project': project
|
||||
}, account_currency)
|
||||
|
||||
@@ -16,7 +16,7 @@ class Account(NestedSet):
|
||||
if frappe.local.flags.ignore_on_update:
|
||||
return
|
||||
else:
|
||||
super().on_update()
|
||||
super(Account, self).on_update()
|
||||
|
||||
def onload(self):
|
||||
frozen_accounts_modifier = frappe.db.get_value("Accounts Settings", "Accounts Settings",
|
||||
|
||||
@@ -58,7 +58,6 @@ class CostCenter(NestedSet):
|
||||
# Validate properties before merging
|
||||
super(CostCenter, self).before_rename(olddn, new_cost_center, merge, "is_group")
|
||||
if not merge:
|
||||
from erpnext.accounts.doctype.account.account import get_name_with_number
|
||||
new_cost_center = get_name_with_number(new_cost_center, self.cost_center_number)
|
||||
|
||||
return new_cost_center
|
||||
@@ -89,3 +88,8 @@ class CostCenter(NestedSet):
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Cost Center", ["lft", "rgt"])
|
||||
|
||||
def get_name_with_number(new_account, account_number):
|
||||
if account_number and not new_account[0].isdigit():
|
||||
new_account = account_number + " - " + new_account
|
||||
return new_account
|
||||
|
||||
@@ -24,7 +24,7 @@ frappe.ui.form.on("Journal Entry", {
|
||||
}, "fa fa-table");
|
||||
}
|
||||
|
||||
if(frm.doc.docstatus==1 && frm.doc.naming_series=="JV-") {
|
||||
if(frm.doc.docstatus==1) {
|
||||
frm.add_custom_button(__('Reverse Journal Entry'), function() {
|
||||
return erpnext.journal_entry.reverse_journal_entry(frm);
|
||||
});
|
||||
|
||||
@@ -23,7 +23,6 @@ frappe.ui.form.on('Payment Entry', {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query("party_type", function() {
|
||||
return{
|
||||
"filters": {
|
||||
@@ -31,7 +30,17 @@ frappe.ui.form.on('Payment Entry', {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query("contact_person", function() {
|
||||
if (frm.doc.party) {
|
||||
return {
|
||||
query: 'frappe.contacts.doctype.contact.contact.contact_query',
|
||||
filters: {
|
||||
link_doctype: frm.doc.party_type,
|
||||
link_name: frm.doc.party
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
frm.set_query("paid_to", function() {
|
||||
var account_types = in_list(["Receive", "Internal Transfer"], frm.doc.payment_type) ?
|
||||
["Bank", "Cash"] : [frappe.boot.party_account_types[frm.doc.party_type]];
|
||||
@@ -114,6 +123,11 @@ frappe.ui.form.on('Payment Entry', {
|
||||
frm.events.set_dynamic_labels(frm);
|
||||
},
|
||||
|
||||
contact_person: function(frm) {
|
||||
frm.set_value("contact_email", "");
|
||||
erpnext.utils.get_contact_details(frm);
|
||||
},
|
||||
|
||||
hide_unhide_fields: function(frm) {
|
||||
var company_currency = frm.doc.company? frappe.get_doc(":Company", frm.doc.company).default_currency: "";
|
||||
|
||||
@@ -146,7 +160,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
frm.toggle_display("set_exchange_gain_loss",
|
||||
(frm.doc.paid_amount && frm.doc.received_amount && frm.doc.difference_amount &&
|
||||
((frm.doc.paid_from_account_currency != company_currency ||
|
||||
frm.doc.paid_to_account_currency != company_currency) &&
|
||||
frm.doc.paid_to_account_currency != company_currency) &&
|
||||
frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency)));
|
||||
|
||||
frm.refresh_fields();
|
||||
@@ -208,7 +222,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
});
|
||||
} else {
|
||||
if(frm.doc.party) {
|
||||
frm.events.party(frm);
|
||||
frm.events.party(frm);
|
||||
}
|
||||
|
||||
if(frm.doc.mode_of_payment) {
|
||||
@@ -230,13 +244,16 @@ frappe.ui.form.on('Payment Entry', {
|
||||
},
|
||||
|
||||
party: function(frm) {
|
||||
if (frm.doc.contact_email || frm.doc.contact_person) {
|
||||
frm.set_value("contact_email", "");
|
||||
frm.set_value("contact_person", "");
|
||||
}
|
||||
if(frm.doc.payment_type && frm.doc.party_type && frm.doc.party) {
|
||||
if(!frm.doc.posting_date) {
|
||||
frappe.msgprint(__("Please select Posting Date before selecting Party"))
|
||||
frm.set_value("party", "");
|
||||
return ;
|
||||
}
|
||||
|
||||
frm.set_party_account_based_on_party = true;
|
||||
|
||||
return frappe.call({
|
||||
@@ -302,7 +319,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
|
||||
}
|
||||
frm.set_value("received_amount", frm.doc.paid_amount);
|
||||
|
||||
|
||||
} else {
|
||||
frm.events.received_amount(frm);
|
||||
}
|
||||
@@ -350,7 +367,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -402,7 +419,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
posting_date: function(frm) {
|
||||
frm.events.paid_from_account_currency(frm);
|
||||
},
|
||||
@@ -415,7 +432,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
|
||||
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
|
||||
}
|
||||
|
||||
|
||||
frm.events.set_unallocated_amount(frm);
|
||||
}
|
||||
|
||||
@@ -425,17 +442,17 @@ frappe.ui.form.on('Payment Entry', {
|
||||
|
||||
target_exchange_rate: function(frm) {
|
||||
frm.set_paid_amount_based_on_received_amount = true;
|
||||
|
||||
|
||||
if (frm.doc.received_amount) {
|
||||
frm.set_value("base_received_amount",
|
||||
flt(frm.doc.received_amount) * flt(frm.doc.target_exchange_rate));
|
||||
|
||||
if(!frm.doc.source_exchange_rate &&
|
||||
|
||||
if(!frm.doc.source_exchange_rate &&
|
||||
(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) {
|
||||
frm.set_value("source_exchange_rate", frm.doc.target_exchange_rate);
|
||||
frm.set_value("base_paid_amount", frm.doc.base_received_amount);
|
||||
}
|
||||
|
||||
|
||||
frm.events.set_unallocated_amount(frm);
|
||||
}
|
||||
frm.set_paid_amount_based_on_received_amount = false;
|
||||
@@ -468,14 +485,14 @@ frappe.ui.form.on('Payment Entry', {
|
||||
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
|
||||
else
|
||||
frm.events.set_unallocated_amount(frm);
|
||||
|
||||
|
||||
frm.set_paid_amount_based_on_received_amount = false;
|
||||
},
|
||||
|
||||
|
||||
reset_received_amount: function(frm) {
|
||||
if(!frm.set_paid_amount_based_on_received_amount &&
|
||||
(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) {
|
||||
|
||||
|
||||
frm.set_value("received_amount", frm.doc.paid_amount);
|
||||
|
||||
if(frm.doc.source_exchange_rate) {
|
||||
@@ -483,7 +500,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
}
|
||||
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
|
||||
}
|
||||
|
||||
|
||||
if(frm.doc.payment_type == "Receive")
|
||||
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount);
|
||||
else
|
||||
@@ -549,7 +566,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
|
||||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier") ||
|
||||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee") ||
|
||||
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student")
|
||||
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student")
|
||||
) {
|
||||
if(total_positive_outstanding > total_negative_outstanding)
|
||||
frm.set_value("paid_amount",
|
||||
@@ -694,7 +711,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
frm.set_value("unallocated_amount", unallocated_amount);
|
||||
frm.trigger("set_difference_amount");
|
||||
},
|
||||
|
||||
|
||||
set_difference_amount: function(frm) {
|
||||
var difference_amount = 0;
|
||||
var base_unallocated_amount = flt(frm.doc.unallocated_amount) *
|
||||
@@ -753,7 +770,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Purchase Order, Purchase Invoice or Journal Entry", [row.idx]));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if(frm.doc.party_type=="Employee" &&
|
||||
!in_list(["Expense Claim", "Journal Entry"], row.reference_doctype)
|
||||
) {
|
||||
|
||||
@@ -376,6 +376,40 @@
|
||||
"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": "party",
|
||||
"fieldname": "contact_person",
|
||||
"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": "Contact",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Contact",
|
||||
"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,
|
||||
@@ -441,6 +475,40 @@
|
||||
"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": "contact_person",
|
||||
"fieldname": "contact_email",
|
||||
"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": "Email",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Email",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
@@ -1972,7 +2040,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-09-11 15:44:28.647566",
|
||||
"modified": "2018-09-25 14:38:48.312629",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Entry",
|
||||
|
||||
@@ -299,12 +299,12 @@ class PaymentEntry(AccountsController):
|
||||
if self.payment_type == "Receive" \
|
||||
and self.base_total_allocated_amount < self.base_received_amount + total_deductions \
|
||||
and self.total_allocated_amount < self.paid_amount + (total_deductions / self.source_exchange_rate):
|
||||
self.unallocated_amount = (self.base_received_amount + total_deductions -
|
||||
self.unallocated_amount = (self.base_received_amount + total_deductions -
|
||||
self.base_total_allocated_amount) / self.source_exchange_rate
|
||||
elif self.payment_type == "Pay" \
|
||||
and self.base_total_allocated_amount < (self.base_paid_amount - total_deductions) \
|
||||
and self.total_allocated_amount < self.received_amount + (total_deductions / self.target_exchange_rate):
|
||||
self.unallocated_amount = (self.base_paid_amount - (total_deductions +
|
||||
self.unallocated_amount = (self.base_paid_amount - (total_deductions +
|
||||
self.base_total_allocated_amount)) / self.target_exchange_rate
|
||||
|
||||
def set_difference_amount(self):
|
||||
@@ -790,7 +790,6 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
|
||||
@frappe.whitelist()
|
||||
def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=None):
|
||||
doc = frappe.get_doc(dt, dn)
|
||||
|
||||
if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) > 0:
|
||||
frappe.throw(_("Can only make payment against unbilled {0}").format(dt))
|
||||
|
||||
@@ -877,7 +876,8 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
||||
pe.mode_of_payment = doc.get("mode_of_payment")
|
||||
pe.party_type = party_type
|
||||
pe.party = doc.get(scrub(party_type))
|
||||
|
||||
pe.contact_person = doc.get("contact_person")
|
||||
pe.contact_email = doc.get("contact_email")
|
||||
pe.ensure_supplier_is_not_blocked()
|
||||
|
||||
pe.paid_from = party_account if payment_type=="Receive" else bank.account
|
||||
|
||||
@@ -123,7 +123,7 @@ class PaymentRequest(Document):
|
||||
"reference_doctype": "Payment Request",
|
||||
"reference_docname": self.name,
|
||||
"payer_email": self.email_to or frappe.session.user,
|
||||
"payer_name": data.customer_name,
|
||||
"payer_name": frappe.safe_encode(data.customer_name),
|
||||
"order_id": self.name,
|
||||
"currency": self.currency
|
||||
})
|
||||
|
||||
@@ -116,6 +116,18 @@ frappe.ui.form.on('Pricing Rule', {
|
||||
};
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
if(frm.doc.__islocal && !frm.doc.applicable_for && (frm.doc.customer || frm.doc.supplier)) {
|
||||
if(frm.doc.customer) {
|
||||
frm.doc.applicable_for = "Customer";
|
||||
frm.doc.selling = 1
|
||||
} else {
|
||||
frm.doc.applicable_for = "Supplier";
|
||||
frm.doc.buying = 1
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
var help_content =
|
||||
`<table class="table table-bordered" style="background-color: #f9f9f9;">
|
||||
|
||||
@@ -384,3 +384,13 @@ def set_transaction_type(args):
|
||||
args.transaction_type = "selling"
|
||||
else:
|
||||
args.transaction_type = "buying"
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_pricing_rule(doctype, docname):
|
||||
doc = frappe.new_doc("Pricing Rule")
|
||||
doc.applicable_for = doctype
|
||||
doc.set(frappe.scrub(doctype), docname)
|
||||
doc.selling = 1 if doctype == "Customer" else 0
|
||||
doc.buying = 1 if doctype == "Supplier" else 0
|
||||
|
||||
return doc
|
||||
@@ -77,8 +77,9 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
||||
}
|
||||
|
||||
if (doc.outstanding_amount > 0 && !cint(doc.is_return)) {
|
||||
cur_frm.add_custom_button(__('Payment Request'),
|
||||
this.make_payment_request, __("Make"));
|
||||
cur_frm.add_custom_button(__('Payment Request'), function() {
|
||||
me.make_payment_request()
|
||||
}, __("Make"));
|
||||
}
|
||||
|
||||
if(doc.docstatus===0) {
|
||||
|
||||
@@ -123,6 +123,7 @@ class PurchaseInvoice(BuyingController):
|
||||
def set_missing_values(self, for_validate=False):
|
||||
if not self.credit_to:
|
||||
self.credit_to = get_party_account("Supplier", self.supplier, self.company)
|
||||
self.party_account_currency = frappe.db.get_value("Account", self.credit_to, "account_currency", cache=True)
|
||||
if not self.due_date:
|
||||
self.due_date = get_due_date(self.posting_date, "Supplier", self.supplier, self.company, self.bill_date)
|
||||
|
||||
@@ -208,7 +209,8 @@ class PurchaseInvoice(BuyingController):
|
||||
if self.update_stock:
|
||||
self.validate_item_code()
|
||||
self.validate_warehouse()
|
||||
warehouse_account = get_warehouse_account_map()
|
||||
if auto_accounting_for_stock:
|
||||
warehouse_account = get_warehouse_account_map()
|
||||
|
||||
for item in self.get("items"):
|
||||
# in case of auto inventory accounting,
|
||||
@@ -377,7 +379,10 @@ class PurchaseInvoice(BuyingController):
|
||||
return gl_entries
|
||||
|
||||
def make_supplier_gl_entry(self, gl_entries):
|
||||
grand_total = self.rounded_total or self.grand_total
|
||||
# Checked both rounding_adjustment and rounded_total
|
||||
# because rounded_total had value even before introcution of posting GLE based on rounded total
|
||||
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
|
||||
|
||||
if grand_total:
|
||||
# Didnot use base_grand_total to book rounding loss gle
|
||||
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
||||
@@ -401,18 +406,23 @@ class PurchaseInvoice(BuyingController):
|
||||
# item gl entries
|
||||
stock_items = self.get_stock_items()
|
||||
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
|
||||
warehouse_account = get_warehouse_account_map()
|
||||
if self.update_stock and self.auto_accounting_for_stock:
|
||||
warehouse_account = get_warehouse_account_map()
|
||||
|
||||
voucher_wise_stock_value = {}
|
||||
if self.update_stock:
|
||||
for d in frappe.get_all('Stock Ledger Entry',
|
||||
fields = ["voucher_detail_no", "stock_value_difference"], filters={'voucher_no': self.name}):
|
||||
voucher_wise_stock_value.setdefault(d.voucher_detail_no, d.stock_value_difference)
|
||||
|
||||
for item in self.get("items"):
|
||||
if flt(item.base_net_amount):
|
||||
account_currency = get_account_currency(item.expense_account)
|
||||
|
||||
if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items:
|
||||
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
|
||||
|
||||
# warehouse account
|
||||
warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
|
||||
* flt(item.qty) * flt(item.conversion_factor), item.precision("base_net_amount"))
|
||||
warehouse_debit_amount = self.make_stock_adjustment_entry(gl_entries,
|
||||
item, voucher_wise_stock_value, account_currency)
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
@@ -552,6 +562,36 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
return gl_entries
|
||||
|
||||
def make_stock_adjustment_entry(self, gl_entries, item, voucher_wise_stock_value, account_currency):
|
||||
net_amt_precision = item.precision("base_net_amount")
|
||||
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
|
||||
|
||||
warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
|
||||
* flt(item.qty) * flt(item.conversion_factor), net_amt_precision)
|
||||
|
||||
# Stock ledger value is not matching with the warehouse amount
|
||||
if (self.update_stock and voucher_wise_stock_value.get(item.name) and
|
||||
warehouse_debit_amount != flt(voucher_wise_stock_value.get(item.name), net_amt_precision)):
|
||||
|
||||
cost_of_goods_sold_account = self.get_company_default("default_expense_account")
|
||||
stock_amount = flt(voucher_wise_stock_value.get(item.name), net_amt_precision)
|
||||
stock_adjustment_amt = warehouse_debit_amount - stock_amount
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": cost_of_goods_sold_account,
|
||||
"against": item.expense_account,
|
||||
"debit": stock_adjustment_amt,
|
||||
"remarks": self.get("remarks") or _("Stock Adjustment"),
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project
|
||||
}, account_currency)
|
||||
)
|
||||
|
||||
warehouse_debit_amount = stock_amount
|
||||
|
||||
return warehouse_debit_amount
|
||||
|
||||
def make_tax_gl_entries(self, gl_entries):
|
||||
# tax table gl entries
|
||||
valuation_tax = {}
|
||||
|
||||
@@ -1742,7 +1742,7 @@
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
@@ -2544,7 +2544,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-09-04 10:11:28.246395",
|
||||
"modified": "2018-10-04 09:05:43.166721",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Item",
|
||||
|
||||
@@ -35,6 +35,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
},
|
||||
|
||||
refresh: function(doc, dt, dn) {
|
||||
const me = this;
|
||||
this._super();
|
||||
if(cur_frm.msgbox && cur_frm.msgbox.$wrapper.is(":visible")) {
|
||||
// hide new msgbox
|
||||
@@ -82,9 +83,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
}
|
||||
}
|
||||
|
||||
if(doc.outstanding_amount>0 && !cint(doc.is_return)) {
|
||||
cur_frm.add_custom_button(__('Payment Request'),
|
||||
this.make_payment_request, __("Make"));
|
||||
if (doc.outstanding_amount>0 && !cint(doc.is_return)) {
|
||||
cur_frm.add_custom_button(__('Payment Request'), function() {
|
||||
me.make_payment_request();
|
||||
}, __("Make"));
|
||||
}
|
||||
|
||||
if(!doc.auto_repeat) {
|
||||
@@ -102,7 +104,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
}
|
||||
|
||||
this.set_default_print_format();
|
||||
var me = this;
|
||||
if (doc.docstatus == 1 && !doc.inter_company_invoice_reference) {
|
||||
frappe.model.with_doc("Customer", me.frm.doc.customer, function() {
|
||||
var customer = frappe.model.get_doc("Customer", me.frm.doc.customer);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
import frappe.defaults
|
||||
from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr
|
||||
from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate
|
||||
from frappe import _, msgprint, throw
|
||||
from erpnext.accounts.party import get_party_account, get_due_date
|
||||
from erpnext.controllers.stock_controller import update_gl_entries_after
|
||||
@@ -54,9 +54,18 @@ class SalesInvoice(SellingController):
|
||||
|
||||
def set_indicator(self):
|
||||
"""Set indicator for portal"""
|
||||
if self.outstanding_amount > 0:
|
||||
if cint(self.is_return) == 1:
|
||||
self.indicator_title = _("Return")
|
||||
self.indicator_color = "darkgrey"
|
||||
elif self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()):
|
||||
self.indicator_color = "orange"
|
||||
self.indicator_title = _("Unpaid")
|
||||
elif self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()):
|
||||
self.indicator_color = "red"
|
||||
self.indicator_title = _("Overdue")
|
||||
elif self.outstanding_amount < 0:
|
||||
self.indicator_title = _("Credit Note Issued")
|
||||
self.indicator_color = "darkgrey"
|
||||
else:
|
||||
self.indicator_color = "green"
|
||||
self.indicator_title = _("Paid")
|
||||
@@ -301,6 +310,7 @@ class SalesInvoice(SellingController):
|
||||
|
||||
if not self.debit_to:
|
||||
self.debit_to = get_party_account("Customer", self.customer, self.company)
|
||||
self.party_account_currency = frappe.db.get_value("Account", self.debit_to, "account_currency", cache=True)
|
||||
if not self.due_date and self.customer:
|
||||
self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company)
|
||||
|
||||
@@ -706,7 +716,9 @@ class SalesInvoice(SellingController):
|
||||
return gl_entries
|
||||
|
||||
def make_customer_gl_entry(self, gl_entries):
|
||||
grand_total = self.rounded_total or self.grand_total
|
||||
# Checked both rounding_adjustment and rounded_total
|
||||
# because rounded_total had value even before introcution of posting GLE based on rounded total
|
||||
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
|
||||
if grand_total:
|
||||
# Didnot use base_grand_total to book rounding loss gle
|
||||
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on transactions against this Subscriber. See timeline below for details'),
|
||||
'fieldname': 'subscriber',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Subscriptions'),
|
||||
'items': ['Subscription']
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
@@ -20,7 +21,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "subscriber",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@@ -29,10 +30,10 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Subscriber",
|
||||
"label": "Customer",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Subscriber",
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@@ -437,6 +438,38 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "generate_invoice_at_period_start",
|
||||
"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": "Generate Invoice At Beginning Of Period",
|
||||
"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,
|
||||
@@ -814,7 +847,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-08-21 16:15:44.533482",
|
||||
"modified": "2018-10-14 10:38:55.545540",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Subscription",
|
||||
@@ -890,4 +923,4 @@
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ class Subscription(Document):
|
||||
invoice = frappe.new_doc('Sales Invoice')
|
||||
invoice.set_posting_time = 1
|
||||
invoice.posting_date = self.current_invoice_start
|
||||
invoice.customer = self.get_customer(self.subscriber)
|
||||
invoice.customer = self.customer
|
||||
|
||||
# Subscription is better suited for service items. I won't update `update_stock`
|
||||
# for that reason
|
||||
@@ -282,13 +282,6 @@ class Subscription(Document):
|
||||
|
||||
return invoice
|
||||
|
||||
@staticmethod
|
||||
def get_customer(subscriber_name):
|
||||
"""
|
||||
Returns the `Customer` linked to the `Subscriber`
|
||||
"""
|
||||
return frappe.db.get_value('Subscriber', subscriber_name, 'customer')
|
||||
|
||||
def get_items_from_plans(self, plans, prorate=0):
|
||||
"""
|
||||
Returns the `Item`s linked to `Subscription Plan`
|
||||
@@ -297,7 +290,7 @@ class Subscription(Document):
|
||||
prorate_factor = get_prorata_factor(self.current_invoice_end, self.current_invoice_start)
|
||||
|
||||
items = []
|
||||
customer = self.get_customer(self.subscriber)
|
||||
customer = self.customer
|
||||
for plan in plans:
|
||||
item_code = frappe.db.get_value("Subscription Plan", plan.plan, "item")
|
||||
if not prorate:
|
||||
@@ -321,6 +314,23 @@ class Subscription(Document):
|
||||
|
||||
self.save()
|
||||
|
||||
@property
|
||||
def is_postpaid_to_invoice(self):
|
||||
return getdate(nowdate()) > getdate(self.current_invoice_end) or \
|
||||
(getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start)) and \
|
||||
not self.has_outstanding_invoice()
|
||||
|
||||
@property
|
||||
def is_prepaid_to_invoice(self):
|
||||
if not self.generate_invoice_at_period_start:
|
||||
return False
|
||||
|
||||
if self.is_new_subscription():
|
||||
return True
|
||||
|
||||
# Check invoice dates and make sure it doesn't have outstanding invoices
|
||||
return getdate(nowdate()) >= getdate(self.current_invoice_start) and not self.has_outstanding_invoice()
|
||||
|
||||
def process_for_active(self):
|
||||
"""
|
||||
Called by `process` if the status of the `Subscription` is 'Active'.
|
||||
@@ -330,7 +340,7 @@ class Subscription(Document):
|
||||
2. Change the `Subscription` status to 'Past Due Date'
|
||||
3. Change the `Subscription` status to 'Cancelled'
|
||||
"""
|
||||
if getdate(nowdate()) > getdate(self.current_invoice_end) or (getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start)) and not self.has_outstanding_invoice():
|
||||
if self.is_postpaid_to_invoice or self.is_prepaid_to_invoice:
|
||||
self.generate_invoice()
|
||||
if self.current_invoice_is_past_due():
|
||||
self.status = 'Past Due Date'
|
||||
@@ -338,7 +348,7 @@ class Subscription(Document):
|
||||
if self.current_invoice_is_past_due() and getdate(nowdate()) > getdate(self.current_invoice_end):
|
||||
self.status = 'Past Due Date'
|
||||
|
||||
if self.cancel_at_period_end and getdate(nowdate()) > self.current_invoice_end:
|
||||
if self.cancel_at_period_end and getdate(nowdate()) > getdate(self.current_invoice_end):
|
||||
self.cancel_subscription_at_period_end()
|
||||
|
||||
def cancel_subscription_at_period_end(self):
|
||||
|
||||
@@ -41,24 +41,14 @@ def create_plan():
|
||||
plan.billing_interval_count = 14
|
||||
plan.insert()
|
||||
|
||||
|
||||
def create_subscriber():
|
||||
if not frappe.db.exists('Subscriber', '_Test Customer'):
|
||||
subscriber = frappe.new_doc('Subscriber')
|
||||
subscriber.subscriber_name = '_Test Customer'
|
||||
subscriber.customer = '_Test Customer'
|
||||
subscriber.insert()
|
||||
|
||||
|
||||
class TestSubscription(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
create_plan()
|
||||
create_subscriber()
|
||||
|
||||
def test_create_subscription_with_trial_with_correct_period(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.trial_period_start = nowdate()
|
||||
subscription.trial_period_end = add_days(nowdate(), 30)
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
@@ -75,7 +65,7 @@ class TestSubscription(unittest.TestCase):
|
||||
|
||||
def test_create_subscription_without_trial_with_correct_period(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
|
||||
@@ -91,7 +81,7 @@ class TestSubscription(unittest.TestCase):
|
||||
|
||||
def test_create_subscription_trial_with_wrong_dates(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.trial_period_end = nowdate()
|
||||
subscription.trial_period_start = add_days(nowdate(), 30)
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
@@ -101,7 +91,7 @@ class TestSubscription(unittest.TestCase):
|
||||
|
||||
def test_create_subscription_multi_with_different_billing_fails(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.trial_period_end = nowdate()
|
||||
subscription.trial_period_start = add_days(nowdate(), 30)
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
@@ -112,7 +102,7 @@ class TestSubscription(unittest.TestCase):
|
||||
|
||||
def test_invoice_is_generated_at_end_of_billing_period(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.start = '2018-01-01'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.insert()
|
||||
@@ -129,7 +119,7 @@ class TestSubscription(unittest.TestCase):
|
||||
|
||||
def test_status_goes_back_to_active_after_invoice_is_paid(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.start = '2018-01-01'
|
||||
subscription.insert()
|
||||
@@ -159,7 +149,7 @@ class TestSubscription(unittest.TestCase):
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.start = '2018-01-01'
|
||||
subscription.insert()
|
||||
@@ -182,7 +172,7 @@ class TestSubscription(unittest.TestCase):
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.start = '2018-01-01'
|
||||
subscription.insert()
|
||||
@@ -200,7 +190,7 @@ class TestSubscription(unittest.TestCase):
|
||||
|
||||
def test_subscription_invoice_days_until_due(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.days_until_due = 10
|
||||
subscription.start = add_months(nowdate(), -1)
|
||||
@@ -218,7 +208,7 @@ class TestSubscription(unittest.TestCase):
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.start = '2018-01-01'
|
||||
subscription.insert()
|
||||
@@ -242,7 +232,7 @@ class TestSubscription(unittest.TestCase):
|
||||
|
||||
def test_subscription_remains_active_during_invoice_period(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
subscription.process() # no changes expected
|
||||
@@ -268,7 +258,7 @@ class TestSubscription(unittest.TestCase):
|
||||
|
||||
def test_subscription_cancelation(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
subscription.cancel_subscription()
|
||||
@@ -284,7 +274,7 @@ class TestSubscription(unittest.TestCase):
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
|
||||
@@ -319,7 +309,7 @@ class TestSubscription(unittest.TestCase):
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
subscription.cancel_subscription()
|
||||
@@ -339,7 +329,7 @@ class TestSubscription(unittest.TestCase):
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
subscription.cancel_subscription()
|
||||
@@ -363,7 +353,7 @@ class TestSubscription(unittest.TestCase):
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.start = '2018-01-01'
|
||||
subscription.insert()
|
||||
@@ -397,7 +387,7 @@ class TestSubscription(unittest.TestCase):
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.start = '2018-01-01'
|
||||
subscription.insert()
|
||||
@@ -434,7 +424,7 @@ class TestSubscription(unittest.TestCase):
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.start = '2018-01-01'
|
||||
subscription.insert()
|
||||
@@ -463,7 +453,7 @@ class TestSubscription(unittest.TestCase):
|
||||
|
||||
def test_restart_active_subscription(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
|
||||
@@ -473,7 +463,7 @@ class TestSubscription(unittest.TestCase):
|
||||
|
||||
def test_subscription_invoice_discount_percentage(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.additional_discount_percentage = 10
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
@@ -488,7 +478,7 @@ class TestSubscription(unittest.TestCase):
|
||||
|
||||
def test_subscription_invoice_discount_amount(self):
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.subscriber = '_Test Customer'
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.additional_discount_amount = 11
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
@@ -500,3 +490,51 @@ class TestSubscription(unittest.TestCase):
|
||||
self.assertEqual(invoice.apply_discount_on, 'Grand Total')
|
||||
|
||||
subscription.delete()
|
||||
|
||||
def test_prepaid_subscriptions(self):
|
||||
# Create a non pre-billed subscription, processing should not create
|
||||
# invoices.
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
subscription.process()
|
||||
|
||||
self.assertEqual(len(subscription.invoices), 0)
|
||||
|
||||
# Change the subscription type to prebilled and process it.
|
||||
# Prepaid invoice should be generated
|
||||
subscription.generate_invoice_at_period_start = True
|
||||
subscription.save()
|
||||
subscription.process()
|
||||
|
||||
self.assertEqual(len(subscription.invoices), 1)
|
||||
|
||||
def test_prepaid_subscriptions_with_prorate_true(self):
|
||||
settings = frappe.get_single('Subscription Settings')
|
||||
to_prorate = settings.prorate
|
||||
settings.prorate = 1
|
||||
settings.save()
|
||||
|
||||
subscription = frappe.new_doc('Subscription')
|
||||
subscription.customer = '_Test Customer'
|
||||
subscription.generate_invoice_at_period_start = True
|
||||
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
|
||||
subscription.save()
|
||||
subscription.cancel_subscription()
|
||||
|
||||
self.assertEqual(len(subscription.invoices), 1)
|
||||
|
||||
current_inv = subscription.get_current_invoice()
|
||||
self.assertEqual(current_inv.status, "Unpaid")
|
||||
|
||||
diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1)
|
||||
plan_days = flt(date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1)
|
||||
prorate_factor = flt(diff / plan_days)
|
||||
|
||||
self.assertEqual(flt(current_inv.grand_total, 2), flt(prorate_factor * 900, 2))
|
||||
|
||||
settings.prorate = to_prorate
|
||||
settings.save()
|
||||
|
||||
subscription.delete()
|
||||
|
||||
@@ -19,6 +19,9 @@ def get_party_tax_withholding_details(ref_doc):
|
||||
|
||||
fy = get_fiscal_year(ref_doc.posting_date, company=ref_doc.company)
|
||||
tax_details = get_tax_withholding_details(tax_withholding_category, fy[0], ref_doc.company)
|
||||
if not tax_details:
|
||||
frappe.throw(_('Please set associated account in Tax Withholding Category {0} against Company {1}')
|
||||
.format(tax_withholding_category, ref_doc.company))
|
||||
tds_amount = get_tds_amount(ref_doc, tax_details, fy)
|
||||
tax_row = get_tax_row(tax_details, tds_amount)
|
||||
return tax_row
|
||||
|
||||
@@ -22,17 +22,18 @@ class DuplicatePartyAccountError(frappe.ValidationError): pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_details(party=None, account=None, party_type="Customer", company=None, posting_date=None,
|
||||
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False, fetch_payment_terms_template=True):
|
||||
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False, fetch_payment_terms_template=True, party_address=None, shipping_address=None):
|
||||
|
||||
if not party:
|
||||
return {}
|
||||
if not frappe.db.exists(party_type, party):
|
||||
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
|
||||
return _get_party_details(party, account, party_type,
|
||||
company, posting_date, bill_date, price_list, currency, doctype, ignore_permissions, fetch_payment_terms_template)
|
||||
company, posting_date, bill_date, price_list, currency, doctype, ignore_permissions, fetch_payment_terms_template, party_address, shipping_address)
|
||||
|
||||
def _get_party_details(party=None, account=None, party_type="Customer", company=None, posting_date=None,
|
||||
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False, fetch_payment_terms_template=True):
|
||||
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False,
|
||||
fetch_payment_terms_template=True, party_address=None, shipping_address=None):
|
||||
|
||||
out = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, bill_date, doctype))
|
||||
party = out[party_type.lower()]
|
||||
@@ -45,7 +46,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
|
||||
|
||||
out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, out.customer_group, out.supplier_group)
|
||||
out["payment_terms_template"] = get_pyt_term_template(party.name, party_type, company)
|
||||
set_address_details(out, party, party_type, doctype, company)
|
||||
set_address_details(out, party, party_type, doctype, company, party_address, shipping_address)
|
||||
set_contact_details(out, party, party_type)
|
||||
set_other_values(out, party, party_type)
|
||||
set_price_list(out, party, party_type, price_list)
|
||||
@@ -71,19 +72,17 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
|
||||
|
||||
return out
|
||||
|
||||
def set_address_details(out, party, party_type, doctype=None, company=None):
|
||||
def set_address_details(out, party, party_type, doctype=None, company=None, party_address=None, shipping_address=None):
|
||||
billing_address_field = "customer_address" if party_type == "Lead" \
|
||||
else party_type.lower() + "_address"
|
||||
out[billing_address_field] = get_default_address(party_type, party.name)
|
||||
out[billing_address_field] = party_address or get_default_address(party_type, party.name)
|
||||
if doctype:
|
||||
out.update(get_fetch_values(doctype, billing_address_field, out[billing_address_field]))
|
||||
|
||||
# address display
|
||||
out.address_display = get_address_display(out[billing_address_field])
|
||||
|
||||
# shipping address
|
||||
if party_type in ["Customer", "Lead"]:
|
||||
out.shipping_address_name = get_party_shipping_address(party_type, party.name)
|
||||
out.shipping_address_name = shipping_address or get_party_shipping_address(party_type, party.name)
|
||||
out.shipping_address = get_address_display(out["shipping_address_name"])
|
||||
if doctype:
|
||||
out.update(get_fetch_values(doctype, 'shipping_address_name', out.shipping_address_name))
|
||||
@@ -97,7 +96,8 @@ def set_address_details(out, party, party_type, doctype=None, company=None):
|
||||
elif doctype and doctype == "Purchase Invoice":
|
||||
out.update(get_company_address(company))
|
||||
if out.company_address:
|
||||
out["shipping_address"] = out["company_address"]
|
||||
out["shipping_address"] = shipping_address or out["company_address"]
|
||||
out.shipping_address_display = get_address_display(out["shipping_address"])
|
||||
out.update(get_fetch_values(doctype, 'shipping_address', out.shipping_address))
|
||||
get_regional_address_details(out, doctype, company)
|
||||
|
||||
|
||||
@@ -161,21 +161,21 @@
|
||||
</td>
|
||||
{% } %}
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Invoiced Amount"], data[i]["currency"]) %}</td>
|
||||
{%= format_currency(data[i]["invoiced_amount"], data[i]["currency"]) %}</td>
|
||||
|
||||
{% if(!filters.show_pdc_in_print) { %}
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Paid Amount"], data[i]["currency"]) %}</td>
|
||||
{%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">
|
||||
{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["Credit Note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %}</td>
|
||||
{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["debit_note"], data[i]["currency"]) %}</td>
|
||||
{% } %}
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Outstanding Amount"], data[i]["currency"]) %}</td>
|
||||
{%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %}</td>
|
||||
|
||||
{% if(filters.show_pdc_in_print) { %}
|
||||
{% if(report.report_name === "Accounts Receivable") { %}
|
||||
<td style="text-align: right">
|
||||
{%= data[i][__("Customer LPO")] %}</td>
|
||||
{%= data[i]["po_no"] %}</td>
|
||||
{% } %}
|
||||
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][__("PDC/LC Date")]) %}</td>
|
||||
<td style="text-align: right">{%= data[i][__("PDC/LC Ref")] %}</td>
|
||||
@@ -189,15 +189,15 @@
|
||||
{% } %}
|
||||
<td><b>{%= __("Total") %}</b></td>
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Invoiced Amount"], data[i]["currency"] ) %}</td>
|
||||
{%= format_currency(data[i]["invoiced_amount"], data[i]["currency"] ) %}</td>
|
||||
|
||||
{% if(!filters.show_pdc_in_print) { %}
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Paid Amount"], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["Credit Note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %} </td>
|
||||
{%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %} </td>
|
||||
{% } %}
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Outstanding Amount"], data[i]["currency"]) %}</td>
|
||||
{%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %}</td>
|
||||
|
||||
{% if(filters.show_pdc_in_print) { %}
|
||||
{% if(report.report_name === "Accounts Receivable") { %}
|
||||
@@ -238,4 +238,4 @@
|
||||
{% } %}
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="text-right text-muted">{{ __("Printed On ") }}{%= frappe.datetime.str_to_user(frappe.datetime.get_datetime_as_string()) %}</p>
|
||||
<p class="text-right text-muted">{{ __("Printed On ") }}{%= frappe.datetime.str_to_user(frappe.datetime.get_datetime_as_string()) %}</p>
|
||||
|
||||
@@ -83,6 +83,7 @@ class ReceivablePayableReport(object):
|
||||
"{range3}-{above}".format(range3=cint(self.filters["range3"])+ 1, above=_("Above"))):
|
||||
columns.append({
|
||||
"label": label,
|
||||
"fieldname":label,
|
||||
"fieldtype": "Currency",
|
||||
"options": "currency",
|
||||
"width": 120
|
||||
@@ -104,9 +105,13 @@ class ReceivablePayableReport(object):
|
||||
]
|
||||
|
||||
if args.get('party_type') == 'Customer':
|
||||
columns += [_("Customer LPO") + ":Data:100"]
|
||||
columns.append({
|
||||
"label": _("Customer LPO"),
|
||||
"fieldtype": "Data",
|
||||
"fieldname": "po_no",
|
||||
"width": 100,
|
||||
})
|
||||
columns += [_("Delivery Note") + ":Data:100"]
|
||||
|
||||
if args.get("party_type") == "Customer":
|
||||
columns += [
|
||||
_("Territory") + ":Link/Territory:80",
|
||||
@@ -448,14 +453,14 @@ def get_pdc_details(party_type, report_date):
|
||||
for pdc in frappe.db.sql("""
|
||||
select
|
||||
pref.reference_name as invoice_no, pent.party, pent.party_type,
|
||||
max(pent.reference_date) as pdc_date, sum(ifnull(pref.allocated_amount,0)) as pdc_amount,
|
||||
max(pent.posting_date) as pdc_date, sum(ifnull(pref.allocated_amount,0)) as pdc_amount,
|
||||
GROUP_CONCAT(pent.reference_no SEPARATOR ', ') as pdc_ref
|
||||
from
|
||||
`tabPayment Entry` as pent inner join `tabPayment Entry Reference` as pref
|
||||
on
|
||||
(pref.parent = pent.name)
|
||||
where
|
||||
pent.docstatus < 2 and pent.reference_date >= %s
|
||||
pent.docstatus < 2 and pent.posting_date > %s
|
||||
and pent.party_type = %s
|
||||
group by pent.party, pref.reference_name""", (report_date, party_type), as_dict=1):
|
||||
pdc_details.setdefault((pdc.invoice_no, pdc.party), pdc)
|
||||
@@ -469,18 +474,23 @@ def get_pdc_details(party_type, report_date):
|
||||
for pdc in frappe.db.sql("""
|
||||
select
|
||||
jea.reference_name as invoice_no, jea.party, jea.party_type,
|
||||
max(je.cheque_date) as pdc_date, sum(ifnull({0},0)) as pdc_amount,
|
||||
max(je.posting_date) as pdc_date, sum(ifnull({0},0)) as pdc_amount,
|
||||
GROUP_CONCAT(je.cheque_no SEPARATOR ', ') as pdc_ref
|
||||
from
|
||||
`tabJournal Entry` as je inner join `tabJournal Entry Account` as jea
|
||||
on
|
||||
(jea.parent = je.name)
|
||||
where
|
||||
je.docstatus < 2 and je.cheque_date >= %s
|
||||
je.docstatus < 2 and je.posting_date > %s
|
||||
and jea.party_type = %s
|
||||
group by jea.party, jea.reference_name""".format(amount_field), (report_date, party_type), as_dict=1):
|
||||
if (pdc.invoice_no, pdc.party) in pdc_details:
|
||||
pdc_details[(pdc.invoice_no, pdc.party)]["pdc_amount"] += pdc.pdc_amount
|
||||
key = (pdc.invoice_no, pdc.party)
|
||||
pdc_details[key]["pdc_amount"] += pdc.pdc_amount
|
||||
if pdc.pdc_ref:
|
||||
pdc_details[key]["pdc_ref"] += ", " + pdc.pdc_ref
|
||||
if pdc.pdc_date:
|
||||
pdc_details[key]["pdc_date"] = max(pdc_details[key]["pdc_date"], pdc.pdc_date)
|
||||
else:
|
||||
pdc_details.setdefault((pdc.invoice_no, pdc.party), pdc)
|
||||
|
||||
|
||||
@@ -3,55 +3,82 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
from frappe.utils import flt
|
||||
from frappe import _
|
||||
|
||||
def execute(filters=None):
|
||||
columns, data = get_columns(), get_data(filters)
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_data(filters):
|
||||
data = frappe.db.sql("""
|
||||
select
|
||||
a.name as asset, a.asset_category, a.status,
|
||||
ds.depreciation_method, a.purchase_date, a.gross_purchase_amount,
|
||||
ds.schedule_date as depreciation_date, ds.depreciation_amount,
|
||||
ds.accumulated_depreciation_amount,
|
||||
(a.gross_purchase_amount - ds.accumulated_depreciation_amount) as amount_after_depreciation,
|
||||
ds.journal_entry as depreciation_entry
|
||||
from
|
||||
`tabAsset` a, `tabDepreciation Schedule` ds
|
||||
where
|
||||
a.name = ds.parent
|
||||
and a.docstatus=1
|
||||
and ifnull(ds.journal_entry, '') != ''
|
||||
and ds.schedule_date between %(from_date)s and %(to_date)s
|
||||
and a.company = %(company)s
|
||||
{conditions}
|
||||
order by
|
||||
a.name asc, ds.schedule_date asc
|
||||
""".format(conditions=get_filter_conditions(filters)), filters, as_dict=1)
|
||||
data = []
|
||||
depreciation_accounts = frappe.db.sql_list(""" select name from tabAccount
|
||||
where ifnull(account_type, '') = 'Depreciation' """)
|
||||
|
||||
filters_data = [["company", "=", filters.get('company')],
|
||||
["posting_date", ">=", filters.get('from_date')],
|
||||
["posting_date", "<=", filters.get('to_date')],
|
||||
["against_voucher_type", "=", "Asset"],
|
||||
["account", "in", depreciation_accounts]]
|
||||
|
||||
if filters.get("asset"):
|
||||
filters_data.append(["against_voucher", "=", filters.get("asset")])
|
||||
|
||||
if filters.get("asset_category"):
|
||||
|
||||
assets = frappe.db.sql_list("""select name from tabAsset
|
||||
where asset_category = %s and docstatus=1""", filters.get("asset_category"))
|
||||
|
||||
filters_data.append(["against_voucher", "in", assets])
|
||||
|
||||
company_finance_book = erpnext.get_default_finance_book(filters.get("company"))
|
||||
if (not filters.get('finance_book') or (filters.get('finance_book') == company_finance_book)):
|
||||
filters_data.append(["finance_book", "in", ['', filters.get('finance_book')]])
|
||||
elif filters.get("finance_book"):
|
||||
filters_data.append(["finance_book", "=", filters.get('finance_book')])
|
||||
|
||||
gl_entries = frappe.get_all('GL Entry',
|
||||
filters= filters_data,
|
||||
fields = ["against_voucher", "debit_in_account_currency as debit", "voucher_no", "posting_date"],
|
||||
order_by= "against_voucher, posting_date")
|
||||
|
||||
if not gl_entries:
|
||||
return data
|
||||
|
||||
assets = [d.against_voucher for d in gl_entries]
|
||||
assets_details = get_assets_details(assets)
|
||||
|
||||
for d in gl_entries:
|
||||
asset_data = assets_details.get(d.against_voucher)
|
||||
if not asset_data.get("accumulated_depreciation_amount"):
|
||||
asset_data.accumulated_depreciation_amount = d.debit
|
||||
else:
|
||||
asset_data.accumulated_depreciation_amount += d.debit
|
||||
|
||||
row = frappe._dict(asset_data)
|
||||
row.update({
|
||||
"depreciation_amount": d.debit,
|
||||
"depreciation_date": d.posting_date,
|
||||
"amount_after_depreciation": (flt(row.gross_purchase_amount) -
|
||||
flt(row.accumulated_depreciation_amount)),
|
||||
"depreciation_entry": d.voucher_no
|
||||
})
|
||||
|
||||
data.append(row)
|
||||
|
||||
return data
|
||||
|
||||
def get_filter_conditions(filters):
|
||||
conditions = ""
|
||||
|
||||
if filters.get("asset"):
|
||||
conditions += " and a.name = %(asset)s"
|
||||
|
||||
if filters.get("asset_category"):
|
||||
conditions += " and a.asset_category = %(asset_category)s"
|
||||
|
||||
company_finance_book = erpnext.get_default_finance_book(filters.get("company"))
|
||||
def get_assets_details(assets):
|
||||
assets_details = {}
|
||||
|
||||
if (not filters.get('finance_book') or (filters.get('finance_book') == company_finance_book)):
|
||||
filters['finance_book'] = company_finance_book
|
||||
conditions += " and ifnull(ds.finance_book, '') in (%(finance_book)s, '') "
|
||||
elif filters.get("finance_book"):
|
||||
conditions += " and ifnull(ds.finance_book, '') = %(finance_book)s"
|
||||
fields = ["name as asset", "gross_purchase_amount",
|
||||
"asset_category", "status", "depreciation_method", "purchase_date"]
|
||||
|
||||
for d in frappe.get_all("Asset", fields = fields, filters = {'name': ('in', assets)}):
|
||||
assets_details.setdefault(d.asset, d)
|
||||
|
||||
return assets_details
|
||||
|
||||
return conditions
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -4,8 +4,16 @@
|
||||
frappe.query_reports["Budget Variance Report"] = {
|
||||
"filters": [
|
||||
{
|
||||
fieldname: "fiscal_year",
|
||||
label: __("Fiscal Year"),
|
||||
fieldname: "from_fiscal_year",
|
||||
label: __("From Fiscal Year"),
|
||||
fieldtype: "Link",
|
||||
options: "Fiscal Year",
|
||||
default: frappe.sys_defaults.fiscal_year,
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: "to_fiscal_year",
|
||||
label: __("To Fiscal Year"),
|
||||
fieldtype: "Link",
|
||||
options: "Fiscal Year",
|
||||
default: frappe.sys_defaults.fiscal_year,
|
||||
@@ -21,7 +29,7 @@ frappe.query_reports["Budget Variance Report"] = {
|
||||
{ "value": "Half-Yearly", "label": __("Half-Yearly") },
|
||||
{ "value": "Yearly", "label": __("Yearly") }
|
||||
],
|
||||
default: "Monthly",
|
||||
default: "Yearly",
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
@@ -46,5 +54,11 @@ frappe.query_reports["Budget Variance Report"] = {
|
||||
fieldtype: "Link",
|
||||
options: "Cost Center"
|
||||
},
|
||||
{
|
||||
fieldname:"show_cumulative",
|
||||
label: __("Show Cumulative Amount"),
|
||||
fieldtype: "Check",
|
||||
default: 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ from frappe.utils import formatdate
|
||||
from erpnext.controllers.trends import get_period_date_ranges, get_period_month_ranges
|
||||
|
||||
from six import iteritems
|
||||
|
||||
from pprint import pprint
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
validate_filters(filters)
|
||||
@@ -19,7 +19,7 @@ def execute(filters=None):
|
||||
else:
|
||||
cost_centers = get_cost_centers(filters)
|
||||
|
||||
period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"])
|
||||
period_month_ranges = get_period_month_ranges(filters["period"], filters["from_fiscal_year"])
|
||||
cam_map = get_cost_center_account_month_map(filters)
|
||||
|
||||
data = []
|
||||
@@ -29,18 +29,28 @@ def execute(filters=None):
|
||||
for account, monthwise_data in iteritems(cost_center_items):
|
||||
row = [cost_center, account]
|
||||
totals = [0, 0, 0]
|
||||
for relevant_months in period_month_ranges:
|
||||
period_data = [0, 0, 0]
|
||||
for month in relevant_months:
|
||||
month_data = monthwise_data.get(month, {})
|
||||
for i, fieldname in enumerate(["target", "actual", "variance"]):
|
||||
value = flt(month_data.get(fieldname))
|
||||
period_data[i] += value
|
||||
totals[i] += value
|
||||
period_data[2] = period_data[0] - period_data[1]
|
||||
row += period_data
|
||||
for year in get_fiscal_years(filters):
|
||||
last_total = 0
|
||||
for relevant_months in period_month_ranges:
|
||||
period_data = [0, 0, 0]
|
||||
for month in relevant_months:
|
||||
if monthwise_data.get(year[0]):
|
||||
month_data = monthwise_data.get(year[0]).get(month, {})
|
||||
for i, fieldname in enumerate(["target", "actual", "variance"]):
|
||||
value = flt(month_data.get(fieldname))
|
||||
period_data[i] += value
|
||||
totals[i] += value
|
||||
|
||||
period_data[0] += last_total
|
||||
|
||||
if(filters.get("show_cumulative")):
|
||||
last_total = period_data[0] - period_data[1]
|
||||
|
||||
period_data[2] = period_data[0] - period_data[1]
|
||||
row += period_data
|
||||
totals[2] = totals[0] - totals[1]
|
||||
row += totals
|
||||
if filters["period"] != "Yearly" :
|
||||
row += totals
|
||||
data.append(row)
|
||||
|
||||
return columns, data
|
||||
@@ -50,21 +60,32 @@ def validate_filters(filters):
|
||||
frappe.throw(_("Filter based on Cost Center is only applicable if Budget Against is selected as Cost Center"))
|
||||
|
||||
def get_columns(filters):
|
||||
columns = [_(filters.get("budget_against")) + ":Link/%s:120"%(filters.get("budget_against")), _("Account") + ":Link/Account:120"]
|
||||
columns = [_(filters.get("budget_against")) + ":Link/%s:80"%(filters.get("budget_against")), _("Account") + ":Link/Account:80"]
|
||||
|
||||
group_months = False if filters["period"] == "Monthly" else True
|
||||
|
||||
for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]):
|
||||
for label in [_("Target") + " (%s)", _("Actual") + " (%s)", _("Variance") + " (%s)"]:
|
||||
if group_months:
|
||||
label = label % (formatdate(from_date, format_string="MMM") + " - " + formatdate(to_date, format_string="MMM"))
|
||||
fiscal_year = get_fiscal_years(filters)
|
||||
|
||||
for year in fiscal_year:
|
||||
for from_date, to_date in get_period_date_ranges(filters["period"], year[0]):
|
||||
if filters["period"] == "Yearly":
|
||||
labels = [_("Budget") + " " + str(year[0]), _("Actual ") + " " + str(year[0]), _("Varaiance ") + " " + str(year[0])]
|
||||
for label in labels:
|
||||
columns.append(label+":Float:80")
|
||||
else:
|
||||
label = label % formatdate(from_date, format_string="MMM")
|
||||
for label in [_("Budget") + " (%s)" + " " + str(year[0]), _("Actual") + " (%s)" + " " + str(year[0]), _("Variance") + " (%s)" + " " + str(year[0])]:
|
||||
if group_months:
|
||||
label = label % (formatdate(from_date, format_string="MMM") + "-" + formatdate(to_date, format_string="MMM"))
|
||||
else:
|
||||
label = label % formatdate(from_date, format_string="MMM")
|
||||
|
||||
columns.append(label+":Float:120")
|
||||
columns.append(label+":Float:80")
|
||||
|
||||
return columns + [_("Total Target") + ":Float:120", _("Total Actual") + ":Float:120",
|
||||
_("Total Variance") + ":Float:120"]
|
||||
if filters["period"] != "Yearly" :
|
||||
return columns + [_("Total Budget") + ":Float:80", _("Total Actual") + ":Float:80",
|
||||
_("Total Variance") + ":Float:80"]
|
||||
else:
|
||||
return columns
|
||||
|
||||
def get_cost_centers(filters):
|
||||
cond = "and 1=1"
|
||||
@@ -81,21 +102,23 @@ def get_cost_center_target_details(filters):
|
||||
cond += " and b.cost_center='%s'" % frappe.db.escape(filters.get("cost_center"))
|
||||
|
||||
return frappe.db.sql("""
|
||||
select b.{budget_against} as budget_against, b.monthly_distribution, ba.account, ba.budget_amount
|
||||
select b.{budget_against} as budget_against, b.monthly_distribution, ba.account, ba.budget_amount,b.fiscal_year
|
||||
from `tabBudget` b, `tabBudget Account` ba
|
||||
where b.name=ba.parent and b.docstatus = 1 and b.fiscal_year=%s
|
||||
and b.budget_against = %s and b.company=%s {cond}
|
||||
where b.name=ba.parent and b.docstatus = 1 and b.fiscal_year between %s and %s
|
||||
and b.budget_against = %s and b.company=%s {cond} order by b.fiscal_year
|
||||
""".format(budget_against=filters.get("budget_against").replace(" ", "_").lower(), cond=cond),
|
||||
(filters.fiscal_year, filters.budget_against, filters.company), as_dict=True)
|
||||
(filters.from_fiscal_year,filters.to_fiscal_year,filters.budget_against, filters.company), as_dict=True)
|
||||
|
||||
|
||||
|
||||
#Get target distribution details of accounts of cost center
|
||||
def get_target_distribution_details(filters):
|
||||
target_details = {}
|
||||
for d in frappe.db.sql("""select md.name, mdp.month, mdp.percentage_allocation
|
||||
from `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md
|
||||
where mdp.parent=md.name and md.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
|
||||
where mdp.parent=md.name and md.fiscal_year between %s and %s order by md.fiscal_year""",(filters.from_fiscal_year, filters.to_fiscal_year), as_dict=1):
|
||||
target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation))
|
||||
|
||||
|
||||
return target_details
|
||||
|
||||
#Get actual details from gl entry
|
||||
@@ -107,7 +130,7 @@ def get_actual_details(name, filters):
|
||||
cc_lft, cc_rgt = frappe.db.get_value("Cost Center", name, ["lft", "rgt"])
|
||||
cond = "lft>='{lft}' and rgt<='{rgt}'".format(lft = cc_lft, rgt=cc_rgt)
|
||||
|
||||
ac_details = frappe.db.sql("""select gl.account, gl.debit, gl.credit,
|
||||
ac_details = frappe.db.sql("""select gl.account, gl.debit, gl.credit,gl.fiscal_year,
|
||||
MONTHNAME(gl.posting_date) as month_name, b.{budget_against} as budget_against
|
||||
from `tabGL Entry` gl, `tabBudget Account` ba, `tabBudget` b
|
||||
where
|
||||
@@ -115,11 +138,11 @@ def get_actual_details(name, filters):
|
||||
and b.docstatus = 1
|
||||
and ba.account=gl.account
|
||||
and b.{budget_against} = gl.{budget_against}
|
||||
and gl.fiscal_year=%s
|
||||
and gl.fiscal_year between %s and %s
|
||||
and b.{budget_against}=%s
|
||||
and exists(select name from `tab{tab}` where name=gl.{budget_against} and {cond}) group by gl.name
|
||||
""".format(tab = filters.budget_against, budget_against = budget_against, cond = cond),
|
||||
(filters.fiscal_year, name), as_dict=1)
|
||||
and exists(select name from `tab{tab}` where name=gl.{budget_against} and {cond}) group by gl.name order by gl.fiscal_year
|
||||
""".format(tab = filters.budget_against, budget_against = budget_against, cond = cond,from_year=filters.from_fiscal_year,to_year=filters.to_fiscal_year),
|
||||
(filters.from_fiscal_year, filters.to_fiscal_year, name), as_dict=1)
|
||||
|
||||
cc_actual_details = {}
|
||||
for d in ac_details:
|
||||
@@ -139,13 +162,12 @@ def get_cost_center_account_month_map(filters):
|
||||
|
||||
for month_id in range(1, 13):
|
||||
month = datetime.date(2013, month_id, 1).strftime('%B')
|
||||
|
||||
cam_map.setdefault(ccd.budget_against, {}).setdefault(ccd.account, {})\
|
||||
cam_map.setdefault(ccd.budget_against, {}).setdefault(ccd.account, {}).setdefault(ccd.fiscal_year,{})\
|
||||
.setdefault(month, frappe._dict({
|
||||
"target": 0.0, "actual": 0.0
|
||||
}))
|
||||
|
||||
tav_dict = cam_map[ccd.budget_against][ccd.account][month]
|
||||
tav_dict = cam_map[ccd.budget_against][ccd.account][ccd.fiscal_year][month]
|
||||
month_percentage = tdd.get(ccd.monthly_distribution, {}).get(month, 0) \
|
||||
if ccd.monthly_distribution else 100.0/12
|
||||
|
||||
@@ -156,3 +178,11 @@ def get_cost_center_account_month_map(filters):
|
||||
tav_dict.actual += flt(ad.debit) - flt(ad.credit)
|
||||
|
||||
return cam_map
|
||||
|
||||
def get_fiscal_years(filters):
|
||||
|
||||
fiscal_year = frappe.db.sql("""select name from `tabFiscal Year` where
|
||||
name between %(from_fiscal_year)s and %(to_fiscal_year)s""",
|
||||
{'from_fiscal_year': filters["from_fiscal_year"], 'to_fiscal_year': filters["to_fiscal_year"]})
|
||||
|
||||
return fiscal_year
|
||||
|
||||
@@ -10,7 +10,7 @@ from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement
|
||||
|
||||
|
||||
def get_mapper_for(mappers, position):
|
||||
mapper_list = filter(lambda x: x['position'] == position, mappers)
|
||||
mapper_list = list(filter(lambda x: x['position'] == position, mappers))
|
||||
return mapper_list[0] if mapper_list else []
|
||||
|
||||
|
||||
@@ -345,13 +345,13 @@ def execute(filters=None):
|
||||
|
||||
# compute net profit / loss
|
||||
income = get_data(
|
||||
filters.company, "Income", "Credit", period_list,
|
||||
filters.company, "Income", "Credit", period_list, filters=filters,
|
||||
accumulated_values=filters.accumulated_values, ignore_closing_entries=True,
|
||||
ignore_accumulated_values_for_fy=True
|
||||
)
|
||||
|
||||
expense = get_data(
|
||||
filters.company, "Expense", "Debit", period_list,
|
||||
filters.company, "Expense", "Debit", period_list, filters=filters,
|
||||
accumulated_values=filters.accumulated_values, ignore_closing_entries=True,
|
||||
ignore_accumulated_values_for_fy=True
|
||||
)
|
||||
|
||||
@@ -238,6 +238,9 @@ def accumulate_values_into_parents(accounts, accounts_by_name, companies):
|
||||
for d in reversed(accounts):
|
||||
if d.parent_account:
|
||||
account = d.parent_account.split('-')[0].strip()
|
||||
if not accounts_by_name.get(account):
|
||||
continue
|
||||
|
||||
for company in companies:
|
||||
accounts_by_name[account][company] = \
|
||||
accounts_by_name[account].get(company, 0.0) + d.get(company, 0.0)
|
||||
@@ -268,8 +271,7 @@ def get_companies(filters):
|
||||
return all_companies, companies
|
||||
|
||||
def get_subsidiary_companies(company):
|
||||
lft, rgt = frappe.get_cached_value('Company',
|
||||
company, ["lft", "rgt"])
|
||||
lft, rgt = frappe.db.get_value('Company', company, ["lft", "rgt"])
|
||||
|
||||
return frappe.db.sql_list("""select name from `tabCompany`
|
||||
where lft >= {0} and rgt <= {1} order by lft, rgt""".format(lft, rgt))
|
||||
|
||||
@@ -339,19 +339,20 @@ def set_gl_entries_by_account(
|
||||
|
||||
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
|
||||
|
||||
accounts = frappe.db.sql_list("""select name from `tabAccount`
|
||||
where lft >= %s and rgt <= %s""", (root_lft, root_rgt))
|
||||
additional_conditions += " and account in ('{}')"\
|
||||
.format("', '".join([frappe.db.escape(d) for d in accounts]))
|
||||
|
||||
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry`
|
||||
where company=%(company)s
|
||||
{additional_conditions}
|
||||
and posting_date <= %(to_date)s
|
||||
and account in (select name from `tabAccount`
|
||||
where lft >= %(lft)s and rgt <= %(rgt)s)
|
||||
order by account, posting_date""".format(additional_conditions=additional_conditions),
|
||||
{
|
||||
"company": company,
|
||||
"from_date": from_date,
|
||||
"to_date": to_date,
|
||||
"lft": root_lft,
|
||||
"rgt": root_rgt,
|
||||
"cost_center": filters.cost_center,
|
||||
"project": filters.project
|
||||
},
|
||||
|
||||
@@ -28,6 +28,24 @@ frappe.query_reports["Item-wise Sales Register"] = {
|
||||
"label": __("Mode of Payment"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Mode of Payment"
|
||||
},
|
||||
{
|
||||
"fieldname":"warehouse",
|
||||
"label": __("Warehouse"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Warehouse"
|
||||
},
|
||||
{
|
||||
"fieldname":"brand",
|
||||
"label": __("Brand"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Brand"
|
||||
},
|
||||
{
|
||||
"fieldname":"item_group",
|
||||
"label": __("Item Group"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Item Group"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@ def execute(filters=None):
|
||||
|
||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
||||
if not filters: filters = {}
|
||||
filters.update({"from_date": filters.get("date_range")[0], "to_date": filters.get("date_range")[1]})
|
||||
filters.update({"from_date": filters.get("date_range") and filters.get("date_range")[0], "to_date": filters.get("date_range") and filters.get("date_range")[1]})
|
||||
columns = get_columns(additional_table_columns)
|
||||
|
||||
company_currency = erpnext.get_company_currency(filters.company)
|
||||
company_currency = erpnext.get_company_currency(filters.get('company'))
|
||||
|
||||
item_list = get_items(filters, additional_query_columns)
|
||||
if item_list:
|
||||
@@ -108,6 +108,23 @@ def get_conditions(filters):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Payment`
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
|
||||
|
||||
if filters.get("warehouse"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s)"""
|
||||
|
||||
|
||||
if filters.get("brand"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s)"""
|
||||
|
||||
if filters.get("item_group"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s)"""
|
||||
|
||||
|
||||
return conditions
|
||||
|
||||
|
||||
@@ -52,6 +52,18 @@ frappe.query_reports["Sales Register"] = {
|
||||
"label": __("Warehouse"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Warehouse"
|
||||
},
|
||||
{
|
||||
"fieldname":"brand",
|
||||
"label": __("Brand"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Brand"
|
||||
},
|
||||
{
|
||||
"fieldname":"item_group",
|
||||
"label": __("Item Group"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Item Group"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -153,6 +153,16 @@ def get_conditions(filters):
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s)"""
|
||||
|
||||
if filters.get("brand"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s)"""
|
||||
|
||||
if filters.get("item_group"):
|
||||
conditions += """ and exists(select name from `tabSales Invoice Item`
|
||||
where parent=`tabSales Invoice`.name
|
||||
and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s)"""
|
||||
|
||||
return conditions
|
||||
|
||||
def get_invoices(filters, additional_query_columns):
|
||||
|
||||
@@ -8,6 +8,7 @@ frappe.query_reports["TDS Computation Summary"] = {
|
||||
"fieldname":"company",
|
||||
"label": __("Company"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Company",
|
||||
"default": frappe.defaults.get_default('company')
|
||||
},
|
||||
{
|
||||
|
||||
@@ -41,8 +41,10 @@ def get_result(filters):
|
||||
for supplier in filters.supplier:
|
||||
tds = frappe.get_doc("Tax Withholding Category", supplier.tax_withholding_category)
|
||||
rate = [d.tax_withholding_rate for d in tds.rates if d.fiscal_year == filters.fiscal_year][0]
|
||||
account = [d.account for d in tds.accounts if d.company == filters.company][0]
|
||||
|
||||
try:
|
||||
account = [d.account for d in tds.accounts if d.company == filters.company][0]
|
||||
except IndexError:
|
||||
account = []
|
||||
total_invoiced_amount, tds_deducted = get_invoice_and_tds_amount(supplier.name, account,
|
||||
filters.company, filters.from_date, filters.to_date)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ frappe.query_reports["TDS Payable Monthly"] = {
|
||||
"fieldname":"company",
|
||||
"label": __("Company"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Company",
|
||||
"default": frappe.defaults.get_default('company')
|
||||
},
|
||||
{
|
||||
|
||||
@@ -64,13 +64,16 @@ def get_result(filters):
|
||||
total_amount_credited += k.credit
|
||||
|
||||
rate = [i.tax_withholding_rate for i in tds_doc.rates
|
||||
if i.fiscal_year == gle_map[d][0].fiscal_year][0]
|
||||
if i.fiscal_year == gle_map[d][0].fiscal_year]
|
||||
|
||||
if getdate(filters.from_date) <= gle_map[d][0].posting_date \
|
||||
and getdate(filters.to_date) >= gle_map[d][0].posting_date:
|
||||
out.append([supplier.pan, supplier.name, tds_doc.name,
|
||||
supplier.supplier_type, rate, total_amount_credited, tds_deducted,
|
||||
gle_map[d][0].posting_date, "Purchase Invoice", d])
|
||||
if rate and len(rate) > 0:
|
||||
rate = rate[0]
|
||||
|
||||
if getdate(filters.from_date) <= gle_map[d][0].posting_date \
|
||||
and getdate(filters.to_date) >= gle_map[d][0].posting_date:
|
||||
out.append([supplier.pan, supplier.name, tds_doc.name,
|
||||
supplier.supplier_type, rate, total_amount_credited, tds_deducted,
|
||||
gle_map[d][0].posting_date, "Purchase Invoice", d])
|
||||
|
||||
return out
|
||||
|
||||
|
||||
@@ -94,6 +94,12 @@ frappe.ui.form.on('Asset', {
|
||||
}, __("Make"));
|
||||
}
|
||||
|
||||
if (!frm.doc.calculate_depreciation) {
|
||||
frm.add_custom_button(__("Depreciation Entry"), function() {
|
||||
frm.trigger("make_journal_entry");
|
||||
}, __("Make"));
|
||||
}
|
||||
|
||||
frm.page.set_inner_btn_group_as_primary(__("Make"));
|
||||
frm.trigger("setup_chart");
|
||||
}
|
||||
@@ -103,6 +109,21 @@ frappe.ui.form.on('Asset', {
|
||||
}
|
||||
},
|
||||
|
||||
make_journal_entry: function(frm) {
|
||||
frappe.call({
|
||||
method: "erpnext.assets.doctype.asset.asset.make_journal_entry",
|
||||
args: {
|
||||
asset_name: frm.doc.name
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
setup_chart: function(frm) {
|
||||
var x_intervals = [frm.doc.purchase_date];
|
||||
var asset_values = [frm.doc.gross_purchase_amount];
|
||||
|
||||
@@ -511,3 +511,34 @@ def get_asset_account(account_name, asset=None, asset_category=None, company=Non
|
||||
.format(account_name.replace('_', ' ').title(), asset_category, company))
|
||||
|
||||
return account
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_journal_entry(asset_name):
|
||||
asset = frappe.get_doc("Asset", asset_name)
|
||||
fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
|
||||
get_depreciation_accounts(asset)
|
||||
|
||||
depreciation_cost_center, depreciation_series = frappe.db.get_value("Company", asset.company,
|
||||
["depreciation_cost_center", "series_for_depreciation_entry"])
|
||||
depreciation_cost_center = asset.cost_center or depreciation_cost_center
|
||||
|
||||
je = frappe.new_doc("Journal Entry")
|
||||
je.voucher_type = "Depreciation Entry"
|
||||
je.naming_series = depreciation_series
|
||||
je.company = asset.company
|
||||
je.remark = "Depreciation Entry against asset {0}".format(asset_name)
|
||||
|
||||
je.append("accounts", {
|
||||
"account": depreciation_expense_account,
|
||||
"reference_type": "Asset",
|
||||
"reference_name": asset.name,
|
||||
"cost_center": depreciation_cost_center
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": accumulated_depreciation_account,
|
||||
"reference_type": "Asset",
|
||||
"reference_name": asset.name
|
||||
})
|
||||
|
||||
return je
|
||||
|
||||
@@ -9,8 +9,9 @@ from frappe.utils import flt, today, getdate, cint
|
||||
|
||||
def post_depreciation_entries(date=None):
|
||||
# Return if automatic booking of asset depreciation is disabled
|
||||
if not frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically"):
|
||||
if not cint(frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically")):
|
||||
return
|
||||
|
||||
if not date:
|
||||
date = today()
|
||||
for asset in get_depreciable_assets(date):
|
||||
@@ -197,4 +198,4 @@ def get_disposal_account_and_cost_center(company):
|
||||
if not depreciation_cost_center:
|
||||
frappe.throw(_("Please set 'Asset Depreciation Cost Center' in Company {0}").format(company))
|
||||
|
||||
return disposal_account, depreciation_cost_center
|
||||
return disposal_account, depreciation_cost_center
|
||||
|
||||
@@ -128,7 +128,7 @@ frappe.ui.form.on("Request for Quotation",{
|
||||
doctype: "Supplier",
|
||||
order_by: "name",
|
||||
fields: ["name"],
|
||||
filters: [["Supplier", "supplier_group_name", "=", args.supplier_group]]
|
||||
filters: [["Supplier", "supplier_group", "=", args.supplier_group]]
|
||||
|
||||
},
|
||||
callback: load_suppliers
|
||||
|
||||
@@ -49,6 +49,10 @@ frappe.ui.form.on("Supplier", {
|
||||
erpnext.utils.make_bank_account(frm.doc.doctype, frm.doc.name);
|
||||
}, __("Make"));
|
||||
|
||||
frm.add_custom_button(__('Pricing Rule'), function () {
|
||||
erpnext.utils.make_pricing_rule(frm.doc.doctype, frm.doc.name);
|
||||
}, __("Make"));
|
||||
|
||||
// indicators
|
||||
erpnext.utils.set_party_dashboard_indicators(frm);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 1,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
@@ -213,6 +214,38 @@
|
||||
"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_transporter",
|
||||
"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 Transporter",
|
||||
"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,
|
||||
@@ -1430,7 +1463,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-09-07 08:48:57.719713",
|
||||
"modified": "2018-10-06 14:31:46.378758",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier",
|
||||
|
||||
@@ -13,6 +13,10 @@ def get_data():
|
||||
{
|
||||
'label': _('Orders'),
|
||||
'items': ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Pricing'),
|
||||
'items': ['Pricing Rule']
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -60,7 +60,12 @@ class SupplierQuotation(BuyingController):
|
||||
for rfq in rfq_list:
|
||||
doc = frappe.get_doc('Request for Quotation', rfq)
|
||||
doc_sup = frappe.get_all('Request for Quotation Supplier', filters=
|
||||
{'parent': doc.name, 'supplier': self.supplier}, fields=['name', 'quote_status'])[0]
|
||||
{'parent': doc.name, 'supplier': self.supplier}, fields=['name', 'quote_status'])
|
||||
|
||||
doc_sup = doc_sup[0] if doc_sup else None
|
||||
if not doc_sup:
|
||||
frappe.throw(_("Supplier {0} not found in {1}").format(self.supplier,
|
||||
"<a href='desk#Form/Request for Quotation/{0}'> Request for Quotation {0} </a>".format(doc.name)))
|
||||
|
||||
quote_status = _('Received')
|
||||
for item in doc.items:
|
||||
@@ -152,4 +157,4 @@ def make_quotation(source_name, target_doc=None):
|
||||
}
|
||||
}, target_doc)
|
||||
|
||||
return doclist
|
||||
return doclist
|
||||
|
||||
@@ -235,6 +235,16 @@ def get_data():
|
||||
"type": "doctype",
|
||||
"name": "GST HSN Code",
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "GSTR-1",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "GSTR-2",
|
||||
"is_query_report": True
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"name": "GST Sales Register",
|
||||
|
||||
@@ -293,6 +293,16 @@ def get_data():
|
||||
"label": _("Patient"),
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"module_name": "Healthcare Practitioner",
|
||||
"color": "#2ecc71",
|
||||
"icon": "fa fa-user-md",
|
||||
"doctype": "Healthcare Practitioner",
|
||||
"type": "link",
|
||||
"link": "List/Healthcare Practitioner",
|
||||
"label": _("Healthcare Practitioner"),
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"module_name": "Patient Appointment",
|
||||
"color": "#934F92",
|
||||
@@ -322,6 +332,36 @@ def get_data():
|
||||
"link": "List/Lab Test",
|
||||
"label": _("Lab Test"),
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"module_name": "Vital Signs",
|
||||
"color": "#2ecc71",
|
||||
"icon": "fa fa-thermometer-empty",
|
||||
"doctype": "Vital Signs",
|
||||
"type": "list",
|
||||
"link": "List/Vital Signs",
|
||||
"label": _("Vital Signs"),
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"module_name": "Clinical Procedure",
|
||||
"color": "#FF888B",
|
||||
"icon": "fa fa-medkit",
|
||||
"doctype": "Clinical Procedure",
|
||||
"type": "list",
|
||||
"link": "List/Clinical Procedure",
|
||||
"label": _("Clinical Procedure"),
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"module_name": "Inpatient Record",
|
||||
"color": "#7578f6",
|
||||
"icon": "fa fa-list-alt",
|
||||
"doctype": "Inpatient Record",
|
||||
"type": "list",
|
||||
"link": "List/Inpatient Record",
|
||||
"label": _("Inpatient Record"),
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"module_name": "Hub",
|
||||
|
||||
@@ -708,22 +708,24 @@ class AccountsController(TransactionBase):
|
||||
def group_similar_items(self):
|
||||
group_item_qty = {}
|
||||
group_item_amount = {}
|
||||
# to update serial number in print
|
||||
count = 0
|
||||
|
||||
for item in self.items:
|
||||
group_item_qty[item.item_code] = group_item_qty.get(item.item_code, 0) + item.qty
|
||||
group_item_amount[item.item_code] = group_item_amount.get(item.item_code, 0) + item.amount
|
||||
|
||||
duplicate_list = []
|
||||
|
||||
for item in self.items:
|
||||
if item.item_code in group_item_qty:
|
||||
count += 1
|
||||
item.qty = group_item_qty[item.item_code]
|
||||
item.amount = group_item_amount[item.item_code]
|
||||
item.rate = flt(flt(item.amount) / flt(item.qty), item.precision("rate"))
|
||||
item.idx = count
|
||||
del group_item_qty[item.item_code]
|
||||
else:
|
||||
duplicate_list.append(item)
|
||||
|
||||
for item in duplicate_list:
|
||||
self.remove(item)
|
||||
|
||||
|
||||
@@ -68,7 +68,8 @@ class BuyingController(StockController):
|
||||
|
||||
# set contact and address details for supplier, if they are not mentioned
|
||||
if getattr(self, "supplier", None):
|
||||
self.update_if_missing(get_party_details(self.supplier, party_type="Supplier", ignore_permissions=self.flags.ignore_permissions, doctype=self.doctype, company=self.company))
|
||||
self.update_if_missing(get_party_details(self.supplier, party_type="Supplier", ignore_permissions=self.flags.ignore_permissions,
|
||||
doctype=self.doctype, company=self.company, party_address=self.supplier_address, shipping_address=self.get('shipping_address')))
|
||||
|
||||
self.set_missing_item_details(for_validate)
|
||||
|
||||
@@ -661,7 +662,7 @@ class BuyingController(StockController):
|
||||
if self.doctype == 'Purchase Invoice' and not self.get('update_stock'):
|
||||
return
|
||||
|
||||
frappe.db.sql("delete from `tabAsset Movement` where reference_name=%s and docstatus = 0", self.name)
|
||||
frappe.db.sql("delete from `tabAsset Movement` where reference_name=%s", self.name)
|
||||
frappe.db.sql("delete from `tabSerial No` where purchase_document_no=%s", self.name)
|
||||
|
||||
def validate_schedule_date(self):
|
||||
|
||||
@@ -137,7 +137,7 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
||||
.format(args.item_code), StockOverReturnError)
|
||||
elif abs(current_stock_qty) > max_returnable_qty:
|
||||
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
|
||||
.format(args.idx, reference_qty, args.item_code), StockOverReturnError)
|
||||
.format(args.idx, max_returnable_qty, args.item_code), StockOverReturnError)
|
||||
|
||||
def get_ref_item_dict(valid_items, ref_item_row):
|
||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||
|
||||
@@ -44,6 +44,7 @@ class SellingController(StockController):
|
||||
set_default_income_account_for_item(self)
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
|
||||
super(SellingController, self).set_missing_values(for_validate)
|
||||
|
||||
# set contact and address details for customer, if they are not mentioned
|
||||
@@ -61,10 +62,10 @@ class SellingController(StockController):
|
||||
party_details = _get_party_details(self.customer,
|
||||
ignore_permissions=self.flags.ignore_permissions,
|
||||
doctype=self.doctype, company=self.company,
|
||||
fetch_payment_terms_template=fetch_payment_terms_template)
|
||||
fetch_payment_terms_template=fetch_payment_terms_template,
|
||||
party_address=self.customer_address, shipping_address=self.shipping_address_name)
|
||||
if not self.meta.get_field("sales_team"):
|
||||
party_details.pop("sales_team")
|
||||
|
||||
self.update_if_missing(party_details)
|
||||
|
||||
elif getattr(self, "lead", None):
|
||||
|
||||
@@ -70,6 +70,7 @@ class calculate_taxes_and_totals(object):
|
||||
if item.rate_with_margin > 0 else item.rate
|
||||
|
||||
item.net_rate = item.rate
|
||||
item.discount_amount = item.price_list_rate - item.rate
|
||||
item.amount = flt(item.rate * item.qty, item.precision("amount"))
|
||||
item.net_amount = item.amount
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
8
erpnext/crm/doctype/market_segment/market_segment.js
Normal file
8
erpnext/crm/doctype/market_segment/market_segment.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('Market Segment', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:subscriber_name",
|
||||
"autoname": "field:market_segment",
|
||||
"beta": 0,
|
||||
"creation": "2018-02-24 11:17:46.809140",
|
||||
"creation": "2018-10-01 09:59:14.479509",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
@@ -20,53 +21,18 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Customer",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "customer.customer_name",
|
||||
"fieldname": "subscriber_name",
|
||||
"fieldname": "market_segment",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Subscriber Name",
|
||||
"label": "Market Segment",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@@ -74,7 +40,7 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
@@ -91,10 +57,10 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-11 15:13:30.056470",
|
||||
"modified": "2018-10-01 09:59:14.479509",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Subscriber",
|
||||
"module": "CRM",
|
||||
"name": "Market Segment",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
@@ -111,7 +77,7 @@
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"role": "Sales Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
@@ -125,5 +91,6 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
10
erpnext/crm/doctype/market_segment/market_segment.py
Normal file
10
erpnext/crm/doctype/market_segment/market_segment.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 MarketSegment(Document):
|
||||
pass
|
||||
23
erpnext/crm/doctype/market_segment/test_market_segment.js
Normal file
23
erpnext/crm/doctype/market_segment/test_market_segment.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: Market Segment", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Market Segment
|
||||
() => frappe.tests.make('Market Segment', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
10
erpnext/crm/doctype/market_segment/test_market_segment.py
Normal file
10
erpnext/crm/doctype/market_segment/test_market_segment.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 TestMarketSegment(unittest.TestCase):
|
||||
pass
|
||||
@@ -107,6 +107,8 @@ erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({
|
||||
if(!this.frm.doc.company && frappe.defaults.get_user_default("Company"))
|
||||
set_multiple(this.frm.doc.doctype, this.frm.doc.name,
|
||||
{ company:frappe.defaults.get_user_default("Company") });
|
||||
if(!this.frm.doc.currency)
|
||||
set_multiple(this.frm.doc.doctype, this.frm.doc.name, { currency:frappe.defaults.get_user_default("Currency") });
|
||||
|
||||
this.setup_queries();
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,8 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Sales Stage', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
||||
96
erpnext/crm/doctype/sales_stage/sales_stage.json
Normal file
96
erpnext/crm/doctype/sales_stage/sales_stage.json
Normal file
@@ -0,0 +1,96 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:stage_name",
|
||||
"beta": 0,
|
||||
"creation": "2018-10-01 09:28:16.399518",
|
||||
"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": "stage_name",
|
||||
"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": "Stage Name",
|
||||
"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-01 09:29:43.230378",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Sales Stage",
|
||||
"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": "Sales Manager",
|
||||
"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": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
@@ -3,7 +3,8 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class Subscriber(Document):
|
||||
class SalesStage(Document):
|
||||
pass
|
||||
@@ -2,15 +2,15 @@
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Subscriber", function (assert) {
|
||||
QUnit.test("test: Sales Stage", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Subscriber
|
||||
() => frappe.tests.make('Subscriber', [
|
||||
// insert a new Sales Stage
|
||||
() => frappe.tests.make('Sales Stage', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
@@ -3,7 +3,8 @@
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestSubscriber(unittest.TestCase):
|
||||
class TestSalesStage(unittest.TestCase):
|
||||
pass
|
||||
0
erpnext/crm/report/lead_details/__init__.py
Normal file
0
erpnext/crm/report/lead_details/__init__.py
Normal file
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-10-22 11:58:16",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 3,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2017-02-24 20:20:28.725080",
|
||||
"modified": "2018-09-26 18:59:46.520731",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"module": "CRM",
|
||||
"name": "Lead Details",
|
||||
"owner": "Administrator",
|
||||
"query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabDynamic Link` on (\n\t\t`tabDynamic Link`.link_name=`tabLead`.name\n\t)\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.name=`tabDynamic Link`.parent\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
|
||||
"prepared_report": 0,
|
||||
"query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n\t`tabLead`.notes as \"Notes::360\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabDynamic Link` on (\n\t\t`tabDynamic Link`.link_name=`tabLead`.name\n\t)\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.name=`tabDynamic Link`.parent\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
|
||||
"ref_doctype": "Lead",
|
||||
"report_name": "Lead Details",
|
||||
"report_type": "Query Report",
|
||||
@@ -1,72 +1,92 @@
|
||||
[
|
||||
{
|
||||
"date_of_birth": "1982-01-03",
|
||||
"date_of_joining": "2001-10-10",
|
||||
"employee_name": "Dikman Shervashidze Shervashidze",
|
||||
"gender": "Female",
|
||||
"user_id": "DikmanShervashidze@example.com"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1959-02-03",
|
||||
"date_of_joining": "1976-09-16",
|
||||
"employee_name": "Zukutakitoteka",
|
||||
"gender": "Female",
|
||||
"user_id": "Zukutakitoteka@example.com"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1982-03-03",
|
||||
"date_of_joining": "2000-06-16",
|
||||
"employee_name": "Hatsue Kashiwagi",
|
||||
"gender": "Female",
|
||||
"user_id": "HatsueKashiwagi@example.com"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1945-04-04",
|
||||
"date_of_joining": "1969-07-01",
|
||||
"employee_name": "Nuran Verkleij",
|
||||
"gender": "Female",
|
||||
"user_id": "NuranVerkleij@example.com"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1978-05-03",
|
||||
"date_of_joining": "1999-12-24",
|
||||
"employee_name": "\u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u041f\u0438\u0440\u043e\u0433\u043e\u0432",
|
||||
"gender": "Male",
|
||||
"user_id": "aromn@example.com"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1964-06-03",
|
||||
"date_of_joining": "1981-08-05",
|
||||
"employee_name": "Tilde Lindqvist",
|
||||
"gender": "Female",
|
||||
"user_id": "TildeLindqvist@example.com"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1982-07-03",
|
||||
"date_of_joining": "2006-06-10",
|
||||
"employee_name": "Micha\u0142 Sobczak",
|
||||
"gender": "Male",
|
||||
"user_id": "MichalSobczak@example.com"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1969-08-03",
|
||||
"date_of_joining": "1993-10-21",
|
||||
"employee_name": "Gabrielle Loftus",
|
||||
"gender": "Female",
|
||||
"user_id": "GabrielleLoftus@example.com"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1982-09-03",
|
||||
"date_of_joining": "2005-09-06",
|
||||
"employee_name": "Vakhita Ryzaev",
|
||||
"gender": "Male",
|
||||
"user_id": "VakhitaRyzaev@example.com"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1985-10-03",
|
||||
"date_of_joining": "2007-12-25",
|
||||
"employee_name": "Charmaine Gaudreau",
|
||||
"gender": "Female",
|
||||
"user_id": "CharmaineGaudreau@example.com"
|
||||
}
|
||||
{
|
||||
"date_of_birth": "1982-01-03",
|
||||
"date_of_joining": "2001-10-10",
|
||||
"employee_name": "Diana Prince",
|
||||
"first_name": "Diana",
|
||||
"last_name": "Prince",
|
||||
"gender": "Female",
|
||||
"user_id": "DianaPrince@example.com"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1959-02-03",
|
||||
"date_of_joining": "1976-09-16",
|
||||
"employee_name": "Zatanna Zatara",
|
||||
"gender": "Female",
|
||||
"user_id": "ZatannaZatara@example.com",
|
||||
"first_name": "Zatanna",
|
||||
"last_name": "Zatara"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1982-03-03",
|
||||
"date_of_joining": "2000-06-16",
|
||||
"employee_name": "Holly Granger",
|
||||
"gender": "Female",
|
||||
"user_id": "HollyGranger@example.com",
|
||||
"first_name": "Holly",
|
||||
"last_name": "Granger"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1945-04-04",
|
||||
"date_of_joining": "1969-07-01",
|
||||
"employee_name": "Neptunia Aquaria",
|
||||
"gender": "Female",
|
||||
"user_id": "NeptuniaAquaria@example.com",
|
||||
"first_name": "Neptunia",
|
||||
"last_name": "Aquaria"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1978-05-03",
|
||||
"date_of_joining": "1999-12-24",
|
||||
"employee_name": "Arthur Curry",
|
||||
"gender": "Male",
|
||||
"user_id": "ArthurCurry@example.com",
|
||||
"first_name": "Arthur",
|
||||
"last_name": "Curry"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1964-06-03",
|
||||
"date_of_joining": "1981-08-05",
|
||||
"employee_name": "Thalia Al Ghul",
|
||||
"gender": "Female",
|
||||
"user_id": "ThaliaAlGhul@example.com",
|
||||
"first_name": "Thalia",
|
||||
"last_name": "Al Ghul"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1982-07-03",
|
||||
"date_of_joining": "2006-06-10",
|
||||
"employee_name": "Maxwell Lord",
|
||||
"gender": "Male",
|
||||
"user_id": "MaxwellLord@example.com",
|
||||
"first_name": "Maxwell",
|
||||
"last_name": "Lord"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1969-08-03",
|
||||
"date_of_joining": "1993-10-21",
|
||||
"employee_name": "Grace Choi",
|
||||
"gender": "Female",
|
||||
"user_id": "GraceChoi@example.com",
|
||||
"first_name": "Grace",
|
||||
"last_name": "Choi"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1982-09-03",
|
||||
"date_of_joining": "2005-09-06",
|
||||
"employee_name": "Vandal Savage",
|
||||
"gender": "Male",
|
||||
"user_id": "VandalSavage@example.com",
|
||||
"first_name": "Vandal",
|
||||
"last_name": "Savage"
|
||||
},
|
||||
{
|
||||
"date_of_birth": "1985-10-03",
|
||||
"date_of_joining": "2007-12-25",
|
||||
"employee_name": "Caitlin Snow",
|
||||
"gender": "Female",
|
||||
"user_id": "CaitlinSnow@example.com",
|
||||
"first_name": "Caitlin",
|
||||
"last_name": "Snow"
|
||||
}
|
||||
]
|
||||
@@ -1,337 +1,493 @@
|
||||
[
|
||||
{
|
||||
"default_supplier": "Asiatic Solutions",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "For Upper Bearing",
|
||||
"image": "/assets/erpnext_demo/images/disc.png",
|
||||
"item_code": "Disc Collars",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Disc Collars"
|
||||
},
|
||||
{
|
||||
"default_supplier": "Nan Duskin",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "CAST IRON, MCMASTER PART NO. 3710T13",
|
||||
"image": "/assets/erpnext_demo/images/bearing.jpg",
|
||||
"item_code": "Bearing Block",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Bearing Block"
|
||||
},
|
||||
{
|
||||
"default_supplier": null,
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}],
|
||||
"description": "Wind Mill C Series for Commercial Use 18ft",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine-2.png",
|
||||
"item_code": "Wind MIll C Series",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind MIll C Series"
|
||||
},
|
||||
{
|
||||
"default_supplier": null,
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}],
|
||||
"description": "Wind Mill A Series for Home Use 9ft",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine.png",
|
||||
"item_code": "Wind Mill A Series",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Mill A Series"
|
||||
},
|
||||
{
|
||||
"default_supplier": null,
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}],
|
||||
"description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
|
||||
"item_code": "Wind Turbine",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Turbine",
|
||||
"has_variants": 1,
|
||||
"has_serial_no": 1,
|
||||
"attributes":[
|
||||
{ "attribute": "Size" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"default_supplier": "HomeBase",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "1.5 in. Diameter x 36 in. Mild Steel Tubing",
|
||||
"image": null,
|
||||
"item_code": "Bearing Pipe",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Bearing Pipe"
|
||||
},
|
||||
{
|
||||
"default_supplier": "New World Realty",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "1/32 in. x 24 in. x 47 in. HDPE Opaque Sheet",
|
||||
"image": null,
|
||||
"item_code": "Wing Sheet",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Wing Sheet"
|
||||
},
|
||||
{
|
||||
"default_supplier": "Eagle Hardware",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "3/16 in. x 6 in. x 6 in. Low Carbon Steel Plate",
|
||||
"image": null,
|
||||
"item_code": "Upper Bearing Plate",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Upper Bearing Plate"
|
||||
},
|
||||
{
|
||||
"default_supplier": "Asiatic Solutions",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "Bearing Assembly",
|
||||
"image": null,
|
||||
"item_code": "Bearing Assembly",
|
||||
"item_group": "Sub Assemblies",
|
||||
"item_name": "Bearing Assembly"
|
||||
},
|
||||
{
|
||||
"default_supplier": "HomeBase",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "3/4 in. x 2 ft. x 4 ft. Pine Plywood",
|
||||
"image": null,
|
||||
"item_code": "Base Plate",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Base Plate",
|
||||
"is_sub_contracted_item": 1
|
||||
},
|
||||
{
|
||||
"default_supplier": "Scott Ties",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "N/A",
|
||||
"image": null,
|
||||
"item_code": "Stand",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Stand"
|
||||
},
|
||||
{
|
||||
"default_supplier": "Eagle Hardware",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "1 in. x 3 in. x 1 ft. Multipurpose Al Alloy Bar",
|
||||
"image": null,
|
||||
"item_code": "Bearing Collar",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Bearing Collar"
|
||||
},
|
||||
{
|
||||
"default_supplier": "Eagle Hardware",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "1/4 in. x 6 in. x 6 in. Mild Steel Plate",
|
||||
"image": null,
|
||||
"item_code": "Base Bearing Plate",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Base Bearing Plate"
|
||||
},
|
||||
{
|
||||
"default_supplier": "HomeBase",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "15/32 in. x 4 ft. x 8 ft. 3-Ply Rtd Sheathing",
|
||||
"image": null,
|
||||
"item_code": "External Disc",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "External Disc"
|
||||
},
|
||||
{
|
||||
"default_supplier": "Eagle Hardware",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "1.25 in. Diameter x 6 ft. Mild Steel Tubing",
|
||||
"image": null,
|
||||
"item_code": "Shaft",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Shaft"
|
||||
},
|
||||
{
|
||||
"default_supplier": "Ks Merchandise",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "1/2 in. x 2 ft. x 4 ft. Pine Plywood",
|
||||
"image": null,
|
||||
"item_code": "Blade Rib",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Blade Rib"
|
||||
},
|
||||
{
|
||||
"default_supplier": "HomeBase",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "For Bearing Collar",
|
||||
"image": null,
|
||||
"item_code": "Internal Disc",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Internal Disc"
|
||||
},
|
||||
{
|
||||
"default_supplier": null,
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}],
|
||||
"description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->\n<p>Size: Small</p>",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
|
||||
"item_code": "Wind Turbine-S",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Turbine-S",
|
||||
"variant_of": "Wind Turbine",
|
||||
"valuation_rate": 300,
|
||||
"attributes":[
|
||||
{
|
||||
"attribute": "Size",
|
||||
"attribute_value": "Small"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default_supplier": null,
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}],
|
||||
"description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->\n<p>Size: Medium</p>",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
|
||||
"item_code": "Wind Turbine-M",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Turbine-M",
|
||||
"variant_of": "Wind Turbine",
|
||||
"valuation_rate": 300,
|
||||
"attributes":[
|
||||
{
|
||||
"attribute": "Size",
|
||||
"attribute_value": "Medium"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"default_supplier": null,
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}],
|
||||
"description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->\n<p>Size: Large</p>",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
|
||||
"item_code": "Wind Turbine-L",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Turbine-L",
|
||||
"variant_of": "Wind Turbine",
|
||||
"valuation_rate": 300,
|
||||
"attributes":[
|
||||
{
|
||||
"attribute": "Size",
|
||||
"attribute_value": "Large"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"is_stock_item": 0,
|
||||
"description": "Wind Mill A Series with Spare Bearing",
|
||||
"item_code": "Wind Mill A Series with Spare Bearing",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Mill A Series with Spare Bearing"
|
||||
},
|
||||
{
|
||||
"default_supplier": "HomeBase",
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "3/4 in. x 2 ft. x 4 ft. Pine Plywood",
|
||||
"image": null,
|
||||
"item_code": "Base Plate Un Painted",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Base Plate Un Painted"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Furnitures",
|
||||
"is_stock_item": 0,
|
||||
"description": "Table",
|
||||
"item_code": "Table",
|
||||
"item_name": "Table",
|
||||
"item_group": "Products"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Furnitures",
|
||||
"is_stock_item": 0,
|
||||
"description": "Chair",
|
||||
"item_code": "Chair",
|
||||
"item_name": "Chair",
|
||||
"item_group": "Products"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Electronic Equipments",
|
||||
"is_stock_item": 0,
|
||||
"description": "Computer",
|
||||
"item_code": "Computer",
|
||||
"item_name": "Computer",
|
||||
"item_group": "Products"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Electronic Equipments",
|
||||
"is_stock_item": 0,
|
||||
"description": "Mobile",
|
||||
"item_code": "Mobile",
|
||||
"item_name": "Mobile",
|
||||
"item_group": "Products"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Softwares",
|
||||
"is_stock_item": 0,
|
||||
"description": "ERP",
|
||||
"item_code": "ERP",
|
||||
"item_name": "ERP",
|
||||
"item_group": "All Item Groups"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Softwares",
|
||||
"is_stock_item": 0,
|
||||
"description": "Autocad",
|
||||
"item_code": "Autocad",
|
||||
"item_name": "Autocad",
|
||||
"item_group": "All Item Groups"
|
||||
},
|
||||
{
|
||||
"is_stock_item": 1,
|
||||
"has_batch_no": 1,
|
||||
"create_new_batch": 1,
|
||||
"valuation_rate": 200,
|
||||
"item_defaults": [{
|
||||
"default_warehouse": "Stores"
|
||||
}],
|
||||
"description": "Corrugated Box",
|
||||
"item_code": "Corrugated Box",
|
||||
"item_name": "Corrugated Box",
|
||||
"item_group": "All Item Groups"
|
||||
}
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "Asiatic Solutions",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "For Upper Bearing",
|
||||
"image": "/assets/erpnext_demo/images/disc.png",
|
||||
"item_code": "Disc Collars",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Disc Collars"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "Nan Duskin",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "CAST IRON, MCMASTER PART NO. 3710T13",
|
||||
"image": "/assets/erpnext_demo/images/bearing.jpg",
|
||||
"item_code": "Bearing Block",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Bearing Block"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": null,
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"description": "Wind Mill C Series for Commercial Use 18ft",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine-2.png",
|
||||
"item_code": "Wind MIll C Series",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind MIll C Series"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": null,
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"description": "Wind Mill A Series for Home Use 9ft",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine.png",
|
||||
"item_code": "Wind Mill A Series",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Mill A Series"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": null,
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
|
||||
"item_code": "Wind Turbine",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Turbine",
|
||||
"has_variants": 1,
|
||||
"has_serial_no": 1,
|
||||
"attributes": [
|
||||
{
|
||||
"attribute": "Size"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "HomeBase",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "1.5 in. Diameter x 36 in. Mild Steel Tubing",
|
||||
"image": null,
|
||||
"item_code": "Bearing Pipe",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Bearing Pipe"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "New World Realty",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "1/32 in. x 24 in. x 47 in. HDPE Opaque Sheet",
|
||||
"image": null,
|
||||
"item_code": "Wing Sheet",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Wing Sheet"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "Eagle Hardware",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "3/16 in. x 6 in. x 6 in. Low Carbon Steel Plate",
|
||||
"image": null,
|
||||
"item_code": "Upper Bearing Plate",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Upper Bearing Plate"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "Asiatic Solutions",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "Bearing Assembly",
|
||||
"image": null,
|
||||
"item_code": "Bearing Assembly",
|
||||
"item_group": "Sub Assemblies",
|
||||
"item_name": "Bearing Assembly"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "HomeBase",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "3/4 in. x 2 ft. x 4 ft. Pine Plywood",
|
||||
"image": null,
|
||||
"item_code": "Base Plate",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Base Plate",
|
||||
"is_sub_contracted_item": 1
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "Scott Ties",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "N/A",
|
||||
"image": null,
|
||||
"item_code": "Stand",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Stand"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "Eagle Hardware",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "1 in. x 3 in. x 1 ft. Multipurpose Al Alloy Bar",
|
||||
"image": null,
|
||||
"item_code": "Bearing Collar",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Bearing Collar"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "Eagle Hardware",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "1/4 in. x 6 in. x 6 in. Mild Steel Plate",
|
||||
"image": null,
|
||||
"item_code": "Base Bearing Plate",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Base Bearing Plate"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "HomeBase",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "15/32 in. x 4 ft. x 8 ft. 3-Ply Rtd Sheathing",
|
||||
"image": null,
|
||||
"item_code": "External Disc",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "External Disc"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "Eagle Hardware",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "1.25 in. Diameter x 6 ft. Mild Steel Tubing",
|
||||
"image": null,
|
||||
"item_code": "Shaft",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Shaft"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "Ks Merchandise",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "1/2 in. x 2 ft. x 4 ft. Pine Plywood",
|
||||
"image": null,
|
||||
"item_code": "Blade Rib",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Blade Rib"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "HomeBase",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "For Bearing Collar",
|
||||
"image": null,
|
||||
"item_code": "Internal Disc",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Internal Disc"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": null,
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->\n<p>Size: Small</p>",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
|
||||
"item_code": "Wind Turbine-S",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Turbine-S",
|
||||
"variant_of": "Wind Turbine",
|
||||
"valuation_rate": 300,
|
||||
"attributes": [
|
||||
{
|
||||
"attribute": "Size",
|
||||
"attribute_value": "Small"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": null,
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->\n<p>Size: Medium</p>",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
|
||||
"item_code": "Wind Turbine-M",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Turbine-M",
|
||||
"variant_of": "Wind Turbine",
|
||||
"valuation_rate": 300,
|
||||
"attributes": [
|
||||
{
|
||||
"attribute": "Size",
|
||||
"attribute_value": "Medium"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": null,
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->\n<p>Size: Large</p>",
|
||||
"image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
|
||||
"item_code": "Wind Turbine-L",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Turbine-L",
|
||||
"variant_of": "Wind Turbine",
|
||||
"valuation_rate": 300,
|
||||
"attributes": [
|
||||
{
|
||||
"attribute": "Size",
|
||||
"attribute_value": "Large"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"is_stock_item": 0,
|
||||
"description": "Wind Mill A Series with Spare Bearing",
|
||||
"item_code": "Wind Mill A Series with Spare Bearing",
|
||||
"item_group": "Products",
|
||||
"item_name": "Wind Mill A Series with Spare Bearing"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_supplier": "HomeBase",
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "3/4 in. x 2 ft. x 4 ft. Pine Plywood",
|
||||
"image": null,
|
||||
"item_code": "Base Plate Un Painted",
|
||||
"item_group": "Raw Material",
|
||||
"item_name": "Base Plate Un Painted"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Furnitures",
|
||||
"is_stock_item": 0,
|
||||
"description": "Table",
|
||||
"item_code": "Table",
|
||||
"item_name": "Table",
|
||||
"item_group": "Products"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Furnitures",
|
||||
"is_stock_item": 0,
|
||||
"description": "Chair",
|
||||
"item_code": "Chair",
|
||||
"item_name": "Chair",
|
||||
"item_group": "Products"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Electronic Equipments",
|
||||
"is_stock_item": 0,
|
||||
"description": "Computer",
|
||||
"item_code": "Computer",
|
||||
"item_name": "Computer",
|
||||
"item_group": "Products"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Electronic Equipments",
|
||||
"is_stock_item": 0,
|
||||
"description": "Mobile",
|
||||
"item_code": "Mobile",
|
||||
"item_name": "Mobile",
|
||||
"item_group": "Products"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Softwares",
|
||||
"is_stock_item": 0,
|
||||
"description": "ERP",
|
||||
"item_code": "ERP",
|
||||
"item_name": "ERP",
|
||||
"item_group": "All Item Groups"
|
||||
},
|
||||
{
|
||||
"is_fixed_asset": 1,
|
||||
"asset_category": "Softwares",
|
||||
"is_stock_item": 0,
|
||||
"description": "Autocad",
|
||||
"item_code": "Autocad",
|
||||
"item_name": "Autocad",
|
||||
"item_group": "All Item Groups"
|
||||
},
|
||||
{
|
||||
"is_stock_item": 1,
|
||||
"has_batch_no": 1,
|
||||
"create_new_batch": 1,
|
||||
"valuation_rate": 200,
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_warehouse": "Stores"
|
||||
}
|
||||
],
|
||||
"description": "Corrugated Box",
|
||||
"item_code": "Corrugated Box",
|
||||
"item_name": "Corrugated Box",
|
||||
"item_group": "All Item Groups"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"is_stock_item": 1,
|
||||
"description": "OnePlus 6",
|
||||
"item_code": "OnePlus 6",
|
||||
"item_name": "OnePlus 6",
|
||||
"item_group": "Products",
|
||||
"domain": "Retail"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"is_stock_item": 1,
|
||||
"description": "OnePlus 6T",
|
||||
"item_code": "OnePlus 6T",
|
||||
"item_name": "OnePlus 6T",
|
||||
"item_group": "Products",
|
||||
"domain": "Retail"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"is_stock_item": 1,
|
||||
"description": "Xiaomi Poco F1",
|
||||
"item_code": "Xiaomi Poco F1",
|
||||
"item_name": "Xiaomi Poco F1",
|
||||
"item_group": "Products",
|
||||
"domain": "Retail"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"is_stock_item": 1,
|
||||
"description": "Iphone XS",
|
||||
"item_code": "Iphone XS",
|
||||
"item_name": "Iphone XS",
|
||||
"item_group": "Products",
|
||||
"domain": "Retail"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"is_stock_item": 1,
|
||||
"description": "Samsung Galaxy S9",
|
||||
"item_code": "Samsung Galaxy S9",
|
||||
"item_name": "Samsung Galaxy S9",
|
||||
"item_group": "Products",
|
||||
"domain": "Retail"
|
||||
},
|
||||
{
|
||||
"item_defaults": [
|
||||
{
|
||||
"default_warehouse": "Finished Goods"
|
||||
}
|
||||
],
|
||||
"is_stock_item": 1,
|
||||
"description": "Sony Bluetooth Headphone",
|
||||
"item_code": "Sony Bluetooth Headphone",
|
||||
"item_name": "Sony Bluetooth Headphone",
|
||||
"item_group": "Products",
|
||||
"domain": "Retail"
|
||||
},
|
||||
{
|
||||
"is_stock_item": 0,
|
||||
"description": "Samsung Phone Repair",
|
||||
"item_code": "Samsung Phone Repair",
|
||||
"item_name": "Samsung Phone Repair",
|
||||
"item_group": "Services",
|
||||
"domain": "Retail"
|
||||
},
|
||||
{
|
||||
"is_stock_item": 0,
|
||||
"description": "OnePlus Phone Repair",
|
||||
"item_code": "OnePlus Phone Repair",
|
||||
"item_name": "OnePlus Phone Repair",
|
||||
"item_group": "Services",
|
||||
"domain": "Retail"
|
||||
},
|
||||
{
|
||||
"is_stock_item": 0,
|
||||
"description": "Xiaomi Phone Repair",
|
||||
"item_code": "Xiaomi Phone Repair",
|
||||
"item_name": "Xiaomi Phone Repair",
|
||||
"item_group": "Services",
|
||||
"domain": "Retail"
|
||||
},
|
||||
{
|
||||
"is_stock_item": 0,
|
||||
"description": "Apple Phone Repair",
|
||||
"item_code": "Apple Phone Repair",
|
||||
"item_name": "Apple Phone Repair",
|
||||
"item_group": "Services",
|
||||
"domain": "Retail"
|
||||
}
|
||||
]
|
||||
@@ -5,104 +5,104 @@
|
||||
"last_name": "User"
|
||||
},
|
||||
{
|
||||
"email": "DikmanShervashidze@example.com",
|
||||
"first_name": "Dikman",
|
||||
"last_name": "Shervashidze"
|
||||
"email": "DianaPrince@example.com",
|
||||
"first_name": "Diana",
|
||||
"last_name": "Prince"
|
||||
},
|
||||
{
|
||||
"email": "Zukutakitoteka@example.com",
|
||||
"first_name": "Zukutakitoteka",
|
||||
"last_name": null
|
||||
"email": "ZatannaZatara@example.com",
|
||||
"first_name": "Zatanna",
|
||||
"last_name": "Zatara"
|
||||
},
|
||||
{
|
||||
"email": "HatsueKashiwagi@example.com",
|
||||
"first_name": "Hatsue",
|
||||
"last_name": "Kashiwagi"
|
||||
"email": "HollyGranger@example.com",
|
||||
"first_name": "Holly",
|
||||
"last_name": "Granger"
|
||||
},
|
||||
{
|
||||
"email": "NuranVerkleij@example.com",
|
||||
"first_name": "Nuran",
|
||||
"last_name": "Verkleij"
|
||||
"email": "NeptuniaAquaria@example.com",
|
||||
"first_name": "Neptunia",
|
||||
"last_name": "Aquaria"
|
||||
},
|
||||
{
|
||||
"email": "aromn@example.com",
|
||||
"first_name": "Arom",
|
||||
"last_name": "Nolan"
|
||||
"email": "ArthurCurry@example.com",
|
||||
"first_name": "Arthur",
|
||||
"last_name": "Curry"
|
||||
},
|
||||
{
|
||||
"email": "TildeLindqvist@example.com",
|
||||
"first_name": "Tilde",
|
||||
"last_name": "Lindqvist"
|
||||
"email": "ThaliaAlGhul@example.com",
|
||||
"first_name": "Thalia",
|
||||
"last_name": "Al Ghul"
|
||||
},
|
||||
{
|
||||
"email": "MichalSobczak@example.com",
|
||||
"first_name": "Micha\u0142",
|
||||
"last_name": "Sobczak"
|
||||
"email": "MaxwellLord@example.com",
|
||||
"first_name": "Maxwell",
|
||||
"last_name": "Lord"
|
||||
},
|
||||
{
|
||||
"email": "GabrielleLoftus@example.com",
|
||||
"first_name": "Gabrielle",
|
||||
"last_name": "Loftus"
|
||||
"email": "GraceChoi@example.com",
|
||||
"first_name": "Grace",
|
||||
"last_name": "Choi"
|
||||
},
|
||||
{
|
||||
"email": "VakhitaRyzaev@example.com",
|
||||
"first_name": "Vakhita",
|
||||
"last_name": "Ryzaev"
|
||||
"email": "VandalSavage@example.com",
|
||||
"first_name": "Vandal",
|
||||
"last_name": "Savage"
|
||||
},
|
||||
{
|
||||
"email": "CharmaineGaudreau@example.com",
|
||||
"first_name": "Charmaine",
|
||||
"last_name": "Gaudreau"
|
||||
"email": "CaitlinSnow@example.com",
|
||||
"first_name": "Caitlin",
|
||||
"last_name": "Snow"
|
||||
},
|
||||
{
|
||||
"email": "RafaelaMaartens@example.com",
|
||||
"first_name": "Rafa\u00ebla",
|
||||
"last_name": "Maartens"
|
||||
"email": "RipHunter@example.com",
|
||||
"first_name": "Rip",
|
||||
"last_name": "Hunter"
|
||||
},
|
||||
{
|
||||
"email": "NuguseYohannes@example.com",
|
||||
"first_name": "Nuguse",
|
||||
"last_name": "Yohannes"
|
||||
"email": "NicholasFury@example.com",
|
||||
"first_name": "Nicholas",
|
||||
"last_name": "Fury"
|
||||
},
|
||||
{
|
||||
"email": "panca@example.com",
|
||||
"first_name": "\u0420\u0430\u0438\u0441\u0430",
|
||||
"last_name": "\u0411\u0435\u043b\u044f\u043a\u043e\u0432\u0430"
|
||||
"email": "PeterParker@example.com",
|
||||
"first_name": "Peter",
|
||||
"last_name": "Parker"
|
||||
},
|
||||
{
|
||||
"email": "CaYinLong@example.com",
|
||||
"first_name": "\u80e4\u9686",
|
||||
"last_name": "\u8521"
|
||||
"email": "JohnConstantine@example.com",
|
||||
"first_name": "John",
|
||||
"last_name": "Constantine"
|
||||
},
|
||||
{
|
||||
"email": "FreddieScott@example.com",
|
||||
"first_name": "Freddie",
|
||||
"last_name": "Scott"
|
||||
"email": "HalJordan@example.com",
|
||||
"first_name": "Hal",
|
||||
"last_name": "Jordan"
|
||||
},
|
||||
{
|
||||
"email": "BergoraVigfusdottir@example.com",
|
||||
"first_name": "Berg\u00fe\u00f3ra",
|
||||
"last_name": "Vigf\u00fasd\u00f3ttir"
|
||||
"email": "VictorStone@example.com",
|
||||
"first_name": "Victor",
|
||||
"last_name": "Stone"
|
||||
},
|
||||
{
|
||||
"email": "WardNajmalDinKalb@example.com",
|
||||
"first_name": "Ward",
|
||||
"last_name": "Kalb"
|
||||
"email": "BruceWayne@example.com",
|
||||
"first_name": "Bruce",
|
||||
"last_name": "Wayne"
|
||||
},
|
||||
{
|
||||
"email": "WanMai@example.com",
|
||||
"first_name": "Wan",
|
||||
"last_name": "Mai"
|
||||
"email": "ClarkKent@example.com",
|
||||
"first_name": "Clark",
|
||||
"last_name": "Kent"
|
||||
},
|
||||
{
|
||||
"email": "LeonAbdulov@example.com",
|
||||
"first_name": "Leon",
|
||||
"last_name": "Abdulov"
|
||||
"email": "BarryAllen@example.com",
|
||||
"first_name": "Barry",
|
||||
"last_name": "Allen"
|
||||
},
|
||||
{
|
||||
"email": "SabinaNovotna@example.com",
|
||||
"first_name": "Sabina",
|
||||
"last_name": "Novotn\u00e1"
|
||||
"email": "KaraZorEl@example.com",
|
||||
"first_name": "Kara",
|
||||
"last_name": "Zor El"
|
||||
},
|
||||
{
|
||||
"email": "demo@erpnext.com",
|
||||
|
||||
@@ -3,8 +3,9 @@ from __future__ import unicode_literals
|
||||
import frappe, sys
|
||||
import erpnext
|
||||
import frappe.utils
|
||||
from erpnext.demo.user import hr, sales, purchase, manufacturing, stock, accounts, projects, fixed_asset, education
|
||||
from erpnext.demo.setup import education, manufacture, setup_data, healthcare
|
||||
from erpnext.demo.user import hr, sales, purchase, manufacturing, stock, accounts, projects, fixed_asset
|
||||
from erpnext.demo.user import education as edu
|
||||
from erpnext.demo.setup import education, manufacture, setup_data, healthcare, retail
|
||||
"""
|
||||
Make a demo
|
||||
|
||||
@@ -28,6 +29,8 @@ def make(domain='Manufacturing', days=100):
|
||||
setup_data.setup(domain)
|
||||
if domain== 'Manufacturing':
|
||||
manufacture.setup_data()
|
||||
elif domain == "Retail":
|
||||
retail.setup_data()
|
||||
elif domain== 'Education':
|
||||
education.setup_data()
|
||||
elif domain== 'Healthcare':
|
||||
@@ -77,13 +80,13 @@ def simulate(domain='Manufacturing', days=100):
|
||||
stock.work()
|
||||
accounts.work()
|
||||
projects.run_projects(current_date)
|
||||
sales.work(domain)
|
||||
# run_messages()
|
||||
|
||||
if domain=='Manufacturing':
|
||||
sales.work()
|
||||
manufacturing.work()
|
||||
elif domain=='Education':
|
||||
education.work()
|
||||
edu.work()
|
||||
|
||||
except:
|
||||
frappe.db.set_global('demo_last_date', current_date)
|
||||
|
||||
@@ -5,7 +5,7 @@ data = {
|
||||
'company_name': 'Wind Power LLC'
|
||||
},
|
||||
'Retail': {
|
||||
'company_name': 'Annapurna Dairy Shop',
|
||||
'company_name': 'Mobile Next',
|
||||
},
|
||||
'Distribution': {
|
||||
'company_name': 'Soltice Hardware',
|
||||
|
||||
65
erpnext/demo/setup/retail.py
Normal file
65
erpnext/demo/setup/retail.py
Normal file
@@ -0,0 +1,65 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import random, json
|
||||
import frappe
|
||||
from frappe.utils import nowdate, add_days
|
||||
from erpnext.demo.setup.setup_data import import_json
|
||||
from erpnext.demo.domains import data
|
||||
|
||||
from six import iteritems
|
||||
|
||||
def setup_data():
|
||||
setup_item()
|
||||
setup_item_price()
|
||||
frappe.db.commit()
|
||||
frappe.clear_cache()
|
||||
|
||||
def setup_item():
|
||||
items = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'item.json')).read())
|
||||
for i in items:
|
||||
if not i.get("domain") == "Retail": continue
|
||||
item = frappe.new_doc('Item')
|
||||
item.update(i)
|
||||
if hasattr(item, 'item_defaults') and item.item_defaults[0].default_warehouse:
|
||||
item.item_defaults[0].company = data.get("Retail").get('company_name')
|
||||
warehouse = frappe.get_all('Warehouse', filters={'warehouse_name': item.item_defaults[0].default_warehouse}, limit=1)
|
||||
if warehouse:
|
||||
item.item_defaults[0].default_warehouse = warehouse[0].name
|
||||
item.insert()
|
||||
|
||||
def setup_item_price():
|
||||
frappe.db.sql("delete from `tabItem Price`")
|
||||
|
||||
standard_selling = {
|
||||
"OnePlus 6": 579,
|
||||
"OnePlus 6T": 600,
|
||||
"Xiaomi Poco F1": 300,
|
||||
"Iphone XS": 999,
|
||||
"Samsung Galaxy S9": 720,
|
||||
"Sony Bluetooth Headphone": 99,
|
||||
"Xiaomi Phone Repair": 10,
|
||||
"Samsung Phone Repair": 20,
|
||||
"OnePlus Phone Repair": 15,
|
||||
"Apple Phone Repair": 30,
|
||||
}
|
||||
|
||||
standard_buying = {
|
||||
"OnePlus 6": 300,
|
||||
"OnePlus 6T": 350,
|
||||
"Xiaomi Poco F1": 200,
|
||||
"Iphone XS": 600,
|
||||
"Samsung Galaxy S9": 500,
|
||||
"Sony Bluetooth Headphone": 69
|
||||
}
|
||||
|
||||
for price_list in ("standard_buying", "standard_selling"):
|
||||
for item, rate in iteritems(locals().get(price_list)):
|
||||
frappe.get_doc({
|
||||
"doctype": "Item Price",
|
||||
"price_list": price_list.replace("_", " ").title(),
|
||||
"item_code": item,
|
||||
"selling": 1 if price_list=="standard_selling" else 0,
|
||||
"buying": 1 if price_list=="standard_buying" else 0,
|
||||
"price_list_rate": rate,
|
||||
"currency": "USD"
|
||||
}).insert()
|
||||
@@ -5,6 +5,7 @@ import frappe, erpnext
|
||||
from frappe.utils.nestedset import get_root_of
|
||||
from frappe.utils import flt, now_datetime, cstr, random_string
|
||||
from frappe.utils.make_random import add_random_children, get_random
|
||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
||||
from erpnext.demo.domains import data
|
||||
from frappe import _
|
||||
|
||||
@@ -14,9 +15,10 @@ def setup(domain):
|
||||
setup_fiscal_year()
|
||||
setup_holiday_list()
|
||||
setup_user()
|
||||
#setup_employee()
|
||||
setup_employee()
|
||||
setup_user_roles()
|
||||
setup_role_permissions()
|
||||
setup_custom_field_for_domain()
|
||||
|
||||
employees = frappe.get_all('Employee', fields=['name', 'date_of_joining'])
|
||||
|
||||
@@ -120,7 +122,7 @@ def setup_user():
|
||||
user = frappe.new_doc("User")
|
||||
user.update(u)
|
||||
user.flags.no_welcome_mail = True
|
||||
user.new_password = 'demo'
|
||||
user.new_password = 'Demo1234567!!!'
|
||||
user.insert()
|
||||
|
||||
def setup_employee():
|
||||
@@ -136,6 +138,8 @@ def setup_employee():
|
||||
salary_component.save()
|
||||
|
||||
import_json('Employee')
|
||||
holiday_list = frappe.db.get_value("Holiday List", {"holiday_list_name": str(now_datetime().year)}, 'name')
|
||||
frappe.db.sql('''update tabEmployee set holiday_list={0}'''.format(holiday_list))
|
||||
|
||||
def setup_salary_structure(employees, salary_slip_based_on_timesheet=0):
|
||||
ss = frappe.new_doc('Salary Structure')
|
||||
@@ -166,12 +170,16 @@ def setup_salary_structure(employees, salary_slip_based_on_timesheet=0):
|
||||
"idx": 1
|
||||
})
|
||||
ss.insert()
|
||||
ss.submit()
|
||||
|
||||
for e in employees:
|
||||
sa = frappe.new_doc("Salary Structure Assignment")
|
||||
sa.employee = e.name
|
||||
sa.salary_structure = ss.name
|
||||
sa.from_date = "2015-01-01"
|
||||
sa.base = random.random() * 10000
|
||||
sa.insert()
|
||||
sa.submit()
|
||||
|
||||
return ss
|
||||
|
||||
@@ -184,52 +192,63 @@ def setup_user_roles():
|
||||
'Nursing User', 'Patient')
|
||||
|
||||
if not frappe.db.get_global('demo_hr_user'):
|
||||
user = frappe.get_doc('User', 'CharmaineGaudreau@example.com')
|
||||
user = frappe.get_doc('User', 'CaitlinSnow@example.com')
|
||||
user.add_roles('HR User', 'HR Manager', 'Accounts User')
|
||||
frappe.db.set_global('demo_hr_user', user.name)
|
||||
update_employee_department(user.name, 'Human Resources')
|
||||
for d in frappe.get_all('User Permission', filters={"user": "CaitlinSnow@example.com"}):
|
||||
frappe.delete_doc('User Permission', d.name)
|
||||
|
||||
if not frappe.db.get_global('demo_sales_user_1'):
|
||||
user = frappe.get_doc('User', 'VakhitaRyzaev@example.com')
|
||||
user = frappe.get_doc('User', 'VandalSavage@example.com')
|
||||
user.add_roles('Sales User')
|
||||
update_employee_department(user.name, 'Sales')
|
||||
frappe.db.set_global('demo_sales_user_1', user.name)
|
||||
|
||||
if not frappe.db.get_global('demo_sales_user_2'):
|
||||
user = frappe.get_doc('User', 'GabrielleLoftus@example.com')
|
||||
user = frappe.get_doc('User', 'GraceChoi@example.com')
|
||||
user.add_roles('Sales User', 'Sales Manager', 'Accounts User')
|
||||
update_employee_department(user.name, 'Sales')
|
||||
frappe.db.set_global('demo_sales_user_2', user.name)
|
||||
|
||||
if not frappe.db.get_global('demo_purchase_user'):
|
||||
user = frappe.get_doc('User', 'MichalSobczak@example.com')
|
||||
user = frappe.get_doc('User', 'MaxwellLord@example.com')
|
||||
user.add_roles('Purchase User', 'Purchase Manager', 'Accounts User', 'Stock User')
|
||||
update_employee_department(user.name, 'Purchase')
|
||||
frappe.db.set_global('demo_purchase_user', user.name)
|
||||
|
||||
if not frappe.db.get_global('demo_manufacturing_user'):
|
||||
user = frappe.get_doc('User', 'NuranVerkleij@example.com')
|
||||
user = frappe.get_doc('User', 'NeptuniaAquaria@example.com')
|
||||
user.add_roles('Manufacturing User', 'Stock User', 'Purchase User', 'Accounts User')
|
||||
update_employee_department(user.name, 'Production')
|
||||
frappe.db.set_global('demo_manufacturing_user', user.name)
|
||||
|
||||
if not frappe.db.get_global('demo_stock_user'):
|
||||
user = frappe.get_doc('User', 'HatsueKashiwagi@example.com')
|
||||
user = frappe.get_doc('User', 'HollyGranger@example.com')
|
||||
user.add_roles('Manufacturing User', 'Stock User', 'Purchase User', 'Accounts User')
|
||||
update_employee_department(user.name, 'Production')
|
||||
frappe.db.set_global('demo_stock_user', user.name)
|
||||
|
||||
if not frappe.db.get_global('demo_accounts_user'):
|
||||
user = frappe.get_doc('User', 'LeonAbdulov@example.com')
|
||||
user = frappe.get_doc('User', 'BarryAllen@example.com')
|
||||
user.add_roles('Accounts User', 'Accounts Manager', 'Sales User', 'Purchase User')
|
||||
update_employee_department(user.name, 'Accounts')
|
||||
frappe.db.set_global('demo_accounts_user', user.name)
|
||||
|
||||
if not frappe.db.get_global('demo_projects_user'):
|
||||
user = frappe.get_doc('User', 'panca@example.com')
|
||||
user = frappe.get_doc('User', 'PeterParker@example.com')
|
||||
user.add_roles('HR User', 'Projects User')
|
||||
update_employee_department(user.name, 'Management')
|
||||
frappe.db.set_global('demo_projects_user', user.name)
|
||||
|
||||
if not frappe.db.get_global('demo_education_user'):
|
||||
user = frappe.get_doc('User', 'aromn@example.com')
|
||||
user = frappe.get_doc('User', 'ArthurCurry@example.com')
|
||||
user.add_roles('Academics User')
|
||||
update_employee_department(user.name, 'Management')
|
||||
frappe.db.set_global('demo_education_user', user.name)
|
||||
|
||||
#Add Expense Approver
|
||||
user = frappe.get_doc('User', 'WanMai@example.com')
|
||||
user = frappe.get_doc('User', 'ClarkKent@example.com')
|
||||
user.add_roles('Expense Approver')
|
||||
|
||||
def setup_leave_allocation():
|
||||
@@ -403,3 +422,19 @@ def import_json(doctype, submit=False, values=None):
|
||||
frappe.db.commit()
|
||||
|
||||
frappe.flags.in_import = False
|
||||
|
||||
def update_employee_department(user_id, department):
|
||||
employee = frappe.db.get_value('Employee', {"user_id": user_id}, 'name')
|
||||
department = frappe.db.get_value('Department', {'department_name': department}, 'name')
|
||||
frappe.db.set_value('Employee', employee, 'department', department)
|
||||
|
||||
def setup_custom_field_for_domain():
|
||||
field = {
|
||||
"Item": [
|
||||
dict(fieldname='domain', label='Domain',
|
||||
fieldtype='Select', hidden=1, default="Manufacturing",
|
||||
options="Manufacturing\nService\nDistribution\nRetail"
|
||||
)
|
||||
]
|
||||
}
|
||||
create_custom_fields(field)
|
||||
|
||||
@@ -56,7 +56,7 @@ def work():
|
||||
if random.random() < 0.5:
|
||||
make_payment_entries("Purchase Invoice", "Accounts Payable")
|
||||
|
||||
if random.random() < 0.1:
|
||||
if random.random() < 0.4:
|
||||
#make payment request against sales invoice
|
||||
sales_invoice_name = get_random("Sales Invoice", filters={"docstatus": 1})
|
||||
if sales_invoice_name:
|
||||
|
||||
@@ -14,34 +14,31 @@ from erpnext.hr.doctype.leave_application.leave_application import (get_leave_ba
|
||||
def work():
|
||||
frappe.set_user(frappe.db.get_global('demo_hr_user'))
|
||||
year, month = frappe.flags.current_date.strftime("%Y-%m").split("-")
|
||||
setup_department_approvers()
|
||||
mark_attendance()
|
||||
make_leave_application()
|
||||
|
||||
# payroll entry
|
||||
if not frappe.db.sql('select name from `tabSalary Slip` where month(adddate(start_date, interval 1 month))=month(curdate())'):
|
||||
# process payroll for previous month
|
||||
payroll_entry = frappe.new_doc("Payroll Entry")
|
||||
payroll_entry.company = frappe.flags.company
|
||||
payroll_entry.payroll_frequency = 'Monthly'
|
||||
|
||||
# select a posting date from the previous month
|
||||
payroll_entry.posting_date = get_last_day(getdate(frappe.flags.current_date) - datetime.timedelta(days=10))
|
||||
payroll_entry.payment_account = frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
||||
|
||||
payroll_entry.set_start_end_dates()
|
||||
|
||||
# based on frequency
|
||||
payroll_entry = get_payroll_entry()
|
||||
payroll_entry.salary_slip_based_on_timesheet = 0
|
||||
payroll_entry.save()
|
||||
payroll_entry.create_salary_slips()
|
||||
payroll_entry.submit_salary_slips()
|
||||
payroll_entry.make_accrual_jv_entry()
|
||||
payroll_entry.submit()
|
||||
# payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
|
||||
# reference_number=random_string(10))
|
||||
|
||||
# based on timesheet
|
||||
payroll_entry = get_payroll_entry()
|
||||
payroll_entry.salary_slip_based_on_timesheet = 1
|
||||
payroll_entry.save()
|
||||
payroll_entry.create_salary_slips()
|
||||
payroll_entry.submit_salary_slips()
|
||||
payroll_entry.make_accrual_jv_entry()
|
||||
payroll_entry.submit()
|
||||
# payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
|
||||
# reference_number=random_string(10))
|
||||
|
||||
@@ -55,12 +52,14 @@ def work():
|
||||
expense_claim.company = frappe.flags.company
|
||||
expense_claim.payable_account = get_payable_account(expense_claim.company)
|
||||
expense_claim.posting_date = frappe.flags.current_date
|
||||
expense_claim.insert()
|
||||
expense_claim.expense_approver = frappe.db.get_global('demo_hr_user')
|
||||
expense_claim.save()
|
||||
|
||||
rand = random.random()
|
||||
|
||||
if rand < 0.4:
|
||||
update_sanctioned_amount(expense_claim)
|
||||
expense_claim.approval_status = 'Approved'
|
||||
expense_claim.submit()
|
||||
|
||||
if random.randint(0, 1):
|
||||
@@ -72,6 +71,19 @@ def work():
|
||||
je.flags.ignore_permissions = 1
|
||||
je.submit()
|
||||
|
||||
def get_payroll_entry():
|
||||
# process payroll for previous month
|
||||
payroll_entry = frappe.new_doc("Payroll Entry")
|
||||
payroll_entry.company = frappe.flags.company
|
||||
payroll_entry.payroll_frequency = 'Monthly'
|
||||
|
||||
# select a posting date from the previous month
|
||||
payroll_entry.posting_date = get_last_day(getdate(frappe.flags.current_date) - datetime.timedelta(days=10))
|
||||
payroll_entry.payment_account = frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
||||
|
||||
payroll_entry.set_start_end_dates()
|
||||
return payroll_entry
|
||||
|
||||
def get_expenses():
|
||||
expenses = []
|
||||
expese_types = frappe.db.sql("""select ect.name, eca.default_account from `tabExpense Claim Type` ect,
|
||||
@@ -114,7 +126,7 @@ def get_timesheet_based_salary_slip_employee():
|
||||
def make_timesheet_records():
|
||||
employees = get_timesheet_based_salary_slip_employee()
|
||||
for e in employees:
|
||||
ts = make_timesheet(e.employee, simulate = True, billable = 1, activity_type=get_random("Activity Type"))
|
||||
ts = make_timesheet(e.employee, simulate = True, billable = 1, activity_type=get_random("Activity Type"), company=frappe.flags.company)
|
||||
frappe.db.commit()
|
||||
|
||||
rand = random.random()
|
||||
@@ -195,3 +207,11 @@ def mark_attendance():
|
||||
attendance.save()
|
||||
attendance.submit()
|
||||
frappe.db.commit()
|
||||
|
||||
def setup_department_approvers():
|
||||
for d in frappe.get_all('Department', filters={'department_name': ['!=', 'All Departments']}):
|
||||
doc = frappe.get_doc('Department', d.name)
|
||||
doc.append("leave_approvers", {'approver': frappe.session.user})
|
||||
doc.append("expense_approvers", {'approver': frappe.session.user})
|
||||
doc.flags.ignore_mandatory = True
|
||||
doc.save()
|
||||
|
||||
@@ -4,25 +4,32 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe, random, erpnext
|
||||
from datetime import timedelta
|
||||
from frappe.utils.make_random import how_many
|
||||
from frappe.desk import query_report
|
||||
from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError
|
||||
from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record
|
||||
|
||||
def work():
|
||||
if random.random() < 0.3: return
|
||||
|
||||
frappe.set_user(frappe.db.get_global('demo_manufacturing_user'))
|
||||
if not frappe.get_all('Sales Order'): return
|
||||
|
||||
from erpnext.projects.doctype.timesheet.timesheet import OverlapError
|
||||
|
||||
ppt = frappe.get_doc("Production Planning Tool", "Production Planning Tool")
|
||||
ppt = frappe.new_doc("Production Plan")
|
||||
ppt.company = erpnext.get_default_company()
|
||||
ppt.use_multi_level_bom = 1
|
||||
# ppt.use_multi_level_bom = 1 #refactored
|
||||
ppt.get_items_from = "Sales Order"
|
||||
ppt.purchase_request_for_warehouse = "Stores - WPL"
|
||||
# ppt.purchase_request_for_warehouse = "Stores - WPL" # refactored
|
||||
ppt.run_method("get_open_sales_orders")
|
||||
if not ppt.get("sales_orders"): return
|
||||
ppt.run_method("get_items")
|
||||
ppt.run_method("raise_work_orders")
|
||||
ppt.run_method("raise_material_requests")
|
||||
ppt.save()
|
||||
ppt.submit()
|
||||
ppt.run_method("raise_work_orders")
|
||||
frappe.db.commit()
|
||||
|
||||
# submit work orders
|
||||
@@ -39,12 +46,12 @@ def work():
|
||||
frappe.db.commit()
|
||||
|
||||
# stores -> wip
|
||||
if random.random() < 0.3:
|
||||
if random.random() < 0.4:
|
||||
for pro in query_report.run("Open Work Orders")["result"][:how_many("Stock Entry for WIP")]:
|
||||
make_stock_entry_from_pro(pro[0], "Material Transfer for Manufacture")
|
||||
|
||||
# wip -> fg
|
||||
if random.random() < 0.3:
|
||||
if random.random() < 0.4:
|
||||
for pro in query_report.run("Work Orders in Progress")["result"][:how_many("Stock Entry for FG")]:
|
||||
make_stock_entry_from_pro(pro[0], "Manufacture")
|
||||
|
||||
@@ -55,17 +62,9 @@ def work():
|
||||
stock_uom = frappe.db.get_value('Item', bom.item, 'stock_uom'),
|
||||
planned_start_date = frappe.flags.current_date)
|
||||
|
||||
# submit time logs
|
||||
for timesheet in frappe.get_all("Timesheet", ["name"], {"docstatus": 0,
|
||||
"work_order": ("!=", ""), "to_time": ("<", frappe.flags.current_date)}):
|
||||
timesheet = frappe.get_doc("Timesheet", timesheet.name)
|
||||
try:
|
||||
timesheet.submit()
|
||||
frappe.db.commit()
|
||||
except OverlapError:
|
||||
pass
|
||||
except WorkstationHolidayError:
|
||||
pass
|
||||
# submit job card
|
||||
if random.random() < 0.4:
|
||||
submit_job_cards()
|
||||
|
||||
def make_stock_entry_from_pro(pro_id, purpose):
|
||||
from erpnext.manufacturing.doctype.work_order.work_order import make_stock_entry
|
||||
@@ -86,3 +85,27 @@ def make_stock_entry_from_pro(pro_id, purpose):
|
||||
except (NegativeStockError, IncorrectValuationRateError, DuplicateEntryForWorkOrderError,
|
||||
OperationsNotCompleteError):
|
||||
frappe.db.rollback()
|
||||
|
||||
def submit_job_cards():
|
||||
work_orders = frappe.get_all("Work Order", ["name", "creation"], {"docstatus": 1, "status": "Not Started"})
|
||||
work_order = random.choice(work_orders)
|
||||
# for work_order in work_orders:
|
||||
start_date = work_order.creation
|
||||
work_order = frappe.get_doc("Work Order", work_order.name)
|
||||
job = frappe.get_all("Job Card", ["name", "operation", "work_order"],
|
||||
{"docstatus": 0, "work_order": work_order.name})
|
||||
|
||||
if not job: return
|
||||
job_map = {}
|
||||
for d in job:
|
||||
job_map[d.operation] = frappe.get_doc("Job Card", d.name)
|
||||
|
||||
for operation in work_order.operations:
|
||||
job = job_map[operation.operation]
|
||||
job.actual_start_date = start_date
|
||||
minutes = operation.get("time_in_mins")
|
||||
random_minutes = random.randint(int(minutes/2), minutes)
|
||||
job.actual_end_date = job.actual_start_date + timedelta(minutes=random_minutes)
|
||||
start_date = job.actual_end_date
|
||||
job.save()
|
||||
job.submit()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import frappe, erpnext
|
||||
from frappe.utils import flt
|
||||
from frappe.utils.make_random import get_random
|
||||
from erpnext.projects.doctype.timesheet.test_timesheet import make_timesheet
|
||||
@@ -19,7 +19,7 @@ def run_projects(current_date):
|
||||
def make_timesheet_for_projects(current_date ):
|
||||
for data in frappe.get_all("Task", ["name", "project"], {"status": "Open", "exp_end_date": ("<", current_date)}):
|
||||
employee = get_random("Employee")
|
||||
ts = make_timesheet(employee, simulate = True, billable = 1,
|
||||
ts = make_timesheet(employee, simulate = True, billable = 1, company = erpnext.get_default_company(),
|
||||
activity_type=get_random("Activity Type"), project=data.project, task =data.name)
|
||||
|
||||
if flt(ts.total_billable_amount) > 0.0:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe, random
|
||||
import frappe, random, json, erpnext
|
||||
from frappe.utils.make_random import how_many, get_random
|
||||
from frappe.desk import query_report
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
@@ -16,14 +16,14 @@ from erpnext.buying.doctype.request_for_quotation.request_for_quotation import \
|
||||
def work():
|
||||
frappe.set_user(frappe.db.get_global('demo_purchase_user'))
|
||||
|
||||
if random.random() < 0.3:
|
||||
if random.random() < 0.6:
|
||||
report = "Items To Be Requested"
|
||||
for row in query_report.run(report)["result"][:random.randint(1, 5)]:
|
||||
item_code, qty = row[0], abs(row[-1])
|
||||
|
||||
mr = make_material_request(item_code, qty)
|
||||
|
||||
if random.random() < 0.3:
|
||||
if random.random() < 0.6:
|
||||
for mr in frappe.get_all('Material Request',
|
||||
filters={'material_request_type': 'Purchase', 'status': 'Open'},
|
||||
limit=random.randint(1,6)):
|
||||
@@ -36,7 +36,7 @@ def work():
|
||||
rfq.submit()
|
||||
|
||||
# Make suppier quotation from RFQ against each supplier.
|
||||
if random.random() < 0.3:
|
||||
if random.random() < 0.6:
|
||||
for rfq in frappe.get_all('Request for Quotation',
|
||||
filters={'status': 'Open'}, limit=random.randint(1, 6)):
|
||||
if not frappe.get_all('Supplier Quotation',
|
||||
@@ -51,15 +51,15 @@ def work():
|
||||
# get supplier details
|
||||
supplier = get_random("Supplier")
|
||||
|
||||
company_currency = frappe.get_cached_value('Company', "Wind Power LLC", "default_currency")
|
||||
party_account_currency = get_party_account_currency("Supplier", supplier, "Wind Power LLC")
|
||||
company_currency = frappe.get_cached_value('Company', erpnext.get_default_company(), "default_currency")
|
||||
party_account_currency = get_party_account_currency("Supplier", supplier, erpnext.get_default_company())
|
||||
if company_currency == party_account_currency:
|
||||
exchange_rate = 1
|
||||
else:
|
||||
exchange_rate = get_exchange_rate(party_account_currency, company_currency, args="for_buying")
|
||||
|
||||
# make supplier quotations
|
||||
if random.random() < 0.2:
|
||||
if random.random() < 0.5:
|
||||
from erpnext.stock.doctype.material_request.material_request import make_supplier_quotation
|
||||
|
||||
report = "Material Requests for which Supplier Quotations are not created"
|
||||
@@ -80,16 +80,20 @@ def work():
|
||||
report = "Requested Items To Be Ordered"
|
||||
for row in query_report.run(report)["result"][:how_many("Purchase Order")]:
|
||||
if row[0] != "'Total'":
|
||||
po = frappe.get_doc(make_purchase_order(row[0]))
|
||||
po.supplier = supplier
|
||||
po.currency = party_account_currency or company_currency
|
||||
po.conversion_rate = exchange_rate
|
||||
po.transaction_date = frappe.flags.current_date
|
||||
po.insert()
|
||||
po.submit()
|
||||
frappe.db.commit()
|
||||
try:
|
||||
po = frappe.get_doc(make_purchase_order(row[0]))
|
||||
po.supplier = supplier
|
||||
po.currency = party_account_currency or company_currency
|
||||
po.conversion_rate = exchange_rate
|
||||
po.transaction_date = frappe.flags.current_date
|
||||
po.insert()
|
||||
po.submit()
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
frappe.db.commit()
|
||||
|
||||
if random.random() < 0.2:
|
||||
if random.random() < 0.5:
|
||||
make_subcontract()
|
||||
|
||||
def make_material_request(item_code, qty):
|
||||
@@ -122,13 +126,14 @@ def add_suppliers(rfq):
|
||||
rfq.append("suppliers", { "supplier": supplier })
|
||||
|
||||
def make_subcontract():
|
||||
from erpnext.buying.doctype.purchase_order.purchase_order import make_stock_entry
|
||||
from erpnext.buying.doctype.purchase_order.purchase_order import make_rm_stock_entry
|
||||
item_code = get_random("Item", {"is_sub_contracted_item": 1})
|
||||
if item_code:
|
||||
# make sub-contract PO
|
||||
po = frappe.new_doc("Purchase Order")
|
||||
po.is_subcontracted = "Yes"
|
||||
po.supplier = get_random("Supplier")
|
||||
po.transaction_date = frappe.flags.current_date # added
|
||||
po.schedule_date = frappe.utils.add_days(frappe.flags.current_date, 7)
|
||||
|
||||
item_code = get_random("Item", {"is_sub_contracted_item": 1})
|
||||
@@ -150,7 +155,20 @@ def make_subcontract():
|
||||
make_material_request(po.items[0].item_code, po.items[0].qty)
|
||||
|
||||
# transfer material for sub-contract
|
||||
stock_entry = frappe.get_doc(make_stock_entry(po.name, po.items[0].item_code))
|
||||
rm_items = get_rm_item(po.items[0], po.supplied_items[0])
|
||||
stock_entry = frappe.get_doc(make_rm_stock_entry(po.name, json.dumps([rm_items])))
|
||||
stock_entry.from_warehouse = "Stores - WPL"
|
||||
stock_entry.to_warehouse = "Supplier - WPL"
|
||||
stock_entry.insert()
|
||||
|
||||
def get_rm_item(items, supplied_items):
|
||||
return {
|
||||
"item_code": items.get("item_code"),
|
||||
"rm_item_code": supplied_items.get("rm_item_code"),
|
||||
"item_name": supplied_items.get("rm_item_code"),
|
||||
"qty": supplied_items.get("required_qty") + random.randint(3,10),
|
||||
"amount": supplied_items.get("amount"),
|
||||
"warehouse": supplied_items.get("reserve_warehouse"),
|
||||
"rate": supplied_items.get("rate"),
|
||||
"stock_uom": supplied_items.get("stock_uom")
|
||||
}
|
||||
|
||||
@@ -3,22 +3,23 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe, random
|
||||
import frappe, random, erpnext
|
||||
from frappe.utils import flt
|
||||
from frappe.utils.make_random import add_random_children, get_random
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
from erpnext.accounts.party import get_party_account_currency
|
||||
from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request, make_payment_entry
|
||||
|
||||
def work():
|
||||
def work(domain="Manufacturing"):
|
||||
frappe.set_user(frappe.db.get_global('demo_sales_user_2'))
|
||||
if random.random() < 0.5:
|
||||
for i in range(random.randint(1,7)):
|
||||
make_opportunity()
|
||||
|
||||
if random.random() < 0.5:
|
||||
for i in range(random.randint(1,3)):
|
||||
make_quotation()
|
||||
for i in range(random.randint(1,7)):
|
||||
if random.random() < 0.5:
|
||||
make_opportunity(domain)
|
||||
|
||||
for i in range(random.randint(1,3)):
|
||||
if random.random() < 0.5:
|
||||
make_quotation(domain)
|
||||
|
||||
# lost quotations / inquiries
|
||||
if random.random() < 0.3:
|
||||
@@ -32,24 +33,27 @@ def work():
|
||||
if opportunity and opportunity.status in ('Open', 'Replied'):
|
||||
opportunity.declare_enquiry_lost('Did not ask')
|
||||
|
||||
if random.random() < 0.3:
|
||||
for i in range(random.randint(1,3)):
|
||||
for i in range(random.randint(1,3)):
|
||||
if random.random() < 0.6:
|
||||
make_sales_order()
|
||||
|
||||
if random.random() < 0.1:
|
||||
if random.random() < 0.5:
|
||||
#make payment request against Sales Order
|
||||
sales_order_name = get_random("Sales Order", filters={"docstatus": 1})
|
||||
if sales_order_name:
|
||||
so = frappe.get_doc("Sales Order", sales_order_name)
|
||||
if flt(so.per_billed) != 100:
|
||||
payment_request = make_payment_request(dt="Sales Order", dn=so.name, recipient_id=so.contact_email,
|
||||
submit_doc=True, mute_email=True, use_dummy_message=True)
|
||||
try:
|
||||
if sales_order_name:
|
||||
so = frappe.get_doc("Sales Order", sales_order_name)
|
||||
if flt(so.per_billed) != 100:
|
||||
payment_request = make_payment_request(dt="Sales Order", dn=so.name, recipient_id=so.contact_email,
|
||||
submit_doc=True, mute_email=True, use_dummy_message=True)
|
||||
|
||||
payment_entry = frappe.get_doc(make_payment_entry(payment_request.name))
|
||||
payment_entry.posting_date = frappe.flags.current_date
|
||||
payment_entry.submit()
|
||||
payment_entry = frappe.get_doc(make_payment_entry(payment_request.name))
|
||||
payment_entry.posting_date = frappe.flags.current_date
|
||||
payment_entry.submit()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def make_opportunity():
|
||||
def make_opportunity(domain):
|
||||
b = frappe.get_doc({
|
||||
"doctype": "Opportunity",
|
||||
"enquiry_from": "Customer",
|
||||
@@ -61,13 +65,13 @@ def make_opportunity():
|
||||
|
||||
add_random_children(b, "items", rows=4, randomize = {
|
||||
"qty": (1, 5),
|
||||
"item_code": ("Item", {"has_variants": 0, "is_fixed_asset": 0})
|
||||
"item_code": ("Item", {"has_variants": 0, "is_fixed_asset": 0, "domain": domain})
|
||||
}, unique="item_code")
|
||||
|
||||
b.insert()
|
||||
frappe.db.commit()
|
||||
|
||||
def make_quotation():
|
||||
def make_quotation(domain):
|
||||
# get open opportunites
|
||||
opportunity = get_random("Opportunity", {"status": "Open", "with_items": 1})
|
||||
|
||||
@@ -84,8 +88,8 @@ def make_quotation():
|
||||
# get customer, currency and exchange_rate
|
||||
customer = get_random("Customer")
|
||||
|
||||
company_currency = frappe.get_cached_value('Company', "Wind Power LLC", "default_currency")
|
||||
party_account_currency = get_party_account_currency("Customer", customer, "Wind Power LLC")
|
||||
company_currency = frappe.get_cached_value('Company', erpnext.get_default_company(), "default_currency")
|
||||
party_account_currency = get_party_account_currency("Customer", customer, erpnext.get_default_company())
|
||||
if company_currency == party_account_currency:
|
||||
exchange_rate = 1
|
||||
else:
|
||||
@@ -104,7 +108,7 @@ def make_quotation():
|
||||
|
||||
add_random_children(qtn, "items", rows=3, randomize = {
|
||||
"qty": (1, 5),
|
||||
"item_code": ("Item", {"has_variants": "0", "is_fixed_asset": 0})
|
||||
"item_code": ("Item", {"has_variants": "0", "is_fixed_asset": 0, "domain": domain})
|
||||
}, unique="item_code")
|
||||
|
||||
qtn.insert()
|
||||
@@ -115,8 +119,8 @@ def make_quotation():
|
||||
def make_sales_order():
|
||||
q = get_random("Quotation", {"status": "Submitted"})
|
||||
if q:
|
||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||
so = frappe.get_doc(make_sales_order(q))
|
||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order as mso
|
||||
so = frappe.get_doc(mso(q))
|
||||
so.transaction_date = frappe.flags.current_date
|
||||
so.delivery_date = frappe.utils.add_days(frappe.flags.current_date, 10)
|
||||
so.insert()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import frappe, random
|
||||
import frappe, random, erpnext
|
||||
from frappe.desk import query_report
|
||||
from erpnext.stock.stock_ledger import NegativeStockError
|
||||
from erpnext.stock.doctype.serial_no.serial_no import SerialNoRequiredError, SerialNoQtyError
|
||||
@@ -45,7 +45,7 @@ def make_delivery_note():
|
||||
# make purchase requests
|
||||
|
||||
# make delivery notes (if possible)
|
||||
if random.random() < 0.3:
|
||||
if random.random() < 0.6:
|
||||
from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
|
||||
report = "Ordered Items To Be Delivered"
|
||||
for so in list(set([r[0] for r in query_report.run(report)["result"]
|
||||
@@ -56,8 +56,9 @@ def make_delivery_note():
|
||||
if not d.expense_account:
|
||||
d.expense_account = ("Cost of Goods Sold - {0}".format(
|
||||
frappe.get_cached_value('Company', dn.company, 'abbr')))
|
||||
dn.insert()
|
||||
|
||||
try:
|
||||
dn.insert()
|
||||
dn.submit()
|
||||
frappe.db.commit()
|
||||
except (NegativeStockError, SerialNoRequiredError, SerialNoQtyError, UnableToSelectBatchError):
|
||||
@@ -68,9 +69,10 @@ def make_stock_reconciliation():
|
||||
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation \
|
||||
import OpeningEntryAccountError, EmptyStockReconciliationItemsError
|
||||
|
||||
if random.random() < 0.1:
|
||||
if random.random() < 0.4:
|
||||
stock_reco = frappe.new_doc("Stock Reconciliation")
|
||||
stock_reco.posting_date = frappe.flags.current_date
|
||||
stock_reco.company = erpnext.get_default_company()
|
||||
stock_reco.get_items_for("Stores - WP")
|
||||
if stock_reco.items:
|
||||
for item in stock_reco.items:
|
||||
@@ -87,7 +89,7 @@ def make_stock_reconciliation():
|
||||
|
||||
def submit_draft_stock_entries():
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry import IncorrectValuationRateError, \
|
||||
DuplicateEntryForProductionOrderError, OperationsNotCompleteError
|
||||
DuplicateEntryForWorkOrderError, OperationsNotCompleteError
|
||||
|
||||
# try posting older drafts (if exists)
|
||||
frappe.db.commit()
|
||||
@@ -98,7 +100,7 @@ def submit_draft_stock_entries():
|
||||
ste.save()
|
||||
ste.submit()
|
||||
frappe.db.commit()
|
||||
except (NegativeStockError, IncorrectValuationRateError, DuplicateEntryForProductionOrderError,
|
||||
except (NegativeStockError, IncorrectValuationRateError, DuplicateEntryForWorkOrderError,
|
||||
OperationsNotCompleteError):
|
||||
frappe.db.rollback()
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ data = {
|
||||
'Patient Encounter',
|
||||
'Lab Test',
|
||||
'Healthcare',
|
||||
'Vital Signs',
|
||||
'Clinical Procedure',
|
||||
'Inpatient Record',
|
||||
'Accounts',
|
||||
'Buying',
|
||||
'Stock',
|
||||
|
||||
@@ -4,7 +4,29 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import get_link_to_form
|
||||
from frappe.model.document import Document
|
||||
|
||||
class StudentLeaveApplication(Document):
|
||||
pass
|
||||
def validate(self):
|
||||
self.validate_duplicate()
|
||||
|
||||
def validate_duplicate(self):
|
||||
data = frappe.db.sql(""" select name from `tabStudent Leave Application`
|
||||
where
|
||||
((%(from_date)s > from_date and %(from_date)s < to_date) or
|
||||
(%(to_date)s > from_date and %(to_date)s < to_date) or
|
||||
(%(from_date)s <= from_date and %(to_date)s >= to_date)) and
|
||||
name != %(name)s and student = %(student)s and docstatus < 2
|
||||
""", {
|
||||
'from_date': self.from_date,
|
||||
'to_date': self.to_date,
|
||||
'student': self.student,
|
||||
'name': self.name
|
||||
}, as_dict=1)
|
||||
|
||||
if data:
|
||||
link = get_link_to_form("Student Leave Application", data[0].name)
|
||||
frappe.throw(_("Leave application {0} already exists against the student {1}")
|
||||
.format(link, self.student))
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('QuickBooks Migrator', {
|
||||
connect: function(frm) {
|
||||
// OAuth requires user intervention to provide application access permissionsto requested scope
|
||||
// Here we open a new window and redirect user to the authorization url.
|
||||
// After user grants us permission to access. We will set authorization details on this doc which will force refresh.
|
||||
window.open(frm.doc.authorization_url)
|
||||
},
|
||||
fetch_data: function(frm) {
|
||||
frm.call("migrate")
|
||||
},
|
||||
onload: function(frm) {
|
||||
frm.trigger("set_indicator")
|
||||
var domain = frappe.urllib.get_base_url()
|
||||
var redirect_url = `${domain}/api/method/erpnext.erpnext_integrations.doctype.quickbooks_migrator.quickbooks_migrator.callback`
|
||||
if (frm.doc.redirect_url != redirect_url) {
|
||||
frm.set_value("redirect_url", redirect_url)
|
||||
}
|
||||
// Instead of changing percentage width and message of single progress bar
|
||||
// Show a different porgress bar for every action after some time remove the finished progress bar
|
||||
// Former approach causes the progress bar to dance back and forth.
|
||||
frm.trigger("set_indicator")
|
||||
frappe.realtime.on("quickbooks_progress_update", function (data) {
|
||||
frm.dashboard.show_progress(data.message, (data.count / data.total) * 100, data.message)
|
||||
if (data.count == data.total) {
|
||||
window.setTimeout( function(message) {frm.dashboard.hide_progress(message)}, 1500, data.messsage)
|
||||
}
|
||||
})
|
||||
},
|
||||
refresh: function(frm) {
|
||||
frm.trigger("set_indicator")
|
||||
if (!frm.doc.access_token) {
|
||||
// Unset access_token signifies that we don't have enough information to connect to quickbooks api and fetch data
|
||||
if (frm.doc.authorization_url) {
|
||||
frm.add_custom_button(__("Connect to Quickbooks"), function () {
|
||||
frm.trigger("connect")
|
||||
});
|
||||
}
|
||||
}
|
||||
if (frm.doc.access_token) {
|
||||
// If we have access_token that means we also have refresh_token we don't need user intervention anymore
|
||||
// All we need now is a Company from erpnext
|
||||
frm.remove_custom_button(__("Connect to Quickbooks"))
|
||||
|
||||
frm.toggle_display("company_settings", 1)
|
||||
frm.set_df_property("company", "reqd", 1)
|
||||
if (frm.doc.company) {
|
||||
frm.add_custom_button(__("Fetch Data"), function () {
|
||||
frm.trigger("fetch_data")
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
set_indicator: function(frm) {
|
||||
var indicator_map = {
|
||||
"Connecting to QuickBooks": [__("Connecting to QuickBooks"), "orange"],
|
||||
"Connected to QuickBooks": [__("Connected to QuickBooks"), "green"],
|
||||
"In Progress": [__("In Progress"), "orange"],
|
||||
"Complete": [__("Complete"), "green"],
|
||||
"Failed": [__("Failed"), "red"],
|
||||
}
|
||||
if (frm.doc.status) {
|
||||
var indicator = indicator_map[frm.doc.status]
|
||||
var label = indicator[0]
|
||||
var color = indicator[1]
|
||||
frm.page.set_indicator(label, color)
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,843 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 1,
|
||||
"creation": "2018-07-10 14:48:16.757030",
|
||||
"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": "status",
|
||||
"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": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Connecting to QuickBooks\nConnected to QuickBooks\nIn Progress\nComplete\nFailed",
|
||||
"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": 1,
|
||||
"collapsible_depends_on": "eval:doc.client_id && doc.client_secret && doc.redirect_url",
|
||||
"columns": 0,
|
||||
"fieldname": "application_settings",
|
||||
"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": "Application Settings",
|
||||
"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": "",
|
||||
"fieldname": "client_id",
|
||||
"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": "Client ID",
|
||||
"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,
|
||||
"default": "",
|
||||
"fieldname": "redirect_url",
|
||||
"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": "Redirect URL",
|
||||
"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,
|
||||
"default": "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer",
|
||||
"fieldname": "token_endpoint",
|
||||
"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": "Token Endpoint",
|
||||
"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": 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": "application_column_break",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"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": "",
|
||||
"fieldname": "client_secret",
|
||||
"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": "Client Secret",
|
||||
"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,
|
||||
"default": "com.intuit.quickbooks.accounting",
|
||||
"fieldname": "scope",
|
||||
"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": "Scope",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"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,
|
||||
"default": "https://quickbooks.api.intuit.com/v3",
|
||||
"fieldname": "api_endpoint",
|
||||
"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": "API Endpoint",
|
||||
"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": 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": 1,
|
||||
"columns": 0,
|
||||
"fieldname": "authorization_settings",
|
||||
"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": "Authorization Settings",
|
||||
"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": "https://appcenter.intuit.com/connect/oauth2",
|
||||
"fieldname": "authorization_endpoint",
|
||||
"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": "Authorization Endpoint",
|
||||
"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": 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": "refresh_token",
|
||||
"fieldtype": "Small Text",
|
||||
"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": "Refresh Token",
|
||||
"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": "code",
|
||||
"fieldtype": "Data",
|
||||
"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": "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": "authorization_column_break",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"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": "authorization_url",
|
||||
"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": "Authorization URL",
|
||||
"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": 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": "access_token",
|
||||
"fieldtype": "Small Text",
|
||||
"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": "Access Token",
|
||||
"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": "quickbooks_company_id",
|
||||
"fieldtype": "Data",
|
||||
"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": "Quickbooks Company ID",
|
||||
"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": "company_settings",
|
||||
"fieldtype": "Section Break",
|
||||
"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": "Company Settings",
|
||||
"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": "company",
|
||||
"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": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"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": "default_shipping_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Default Shipping Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "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": "default_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Default Warehouse",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Warehouse",
|
||||
"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": "company_column_break",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"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": "default_cost_center",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Default Cost Center",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Cost Center",
|
||||
"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": "undeposited_funds_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Undeposited Funds Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "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
|
||||
}
|
||||
],
|
||||
"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-17 03:12:53.506229",
|
||||
"modified_by": "Administrator",
|
||||
"module": "ERPNext Integrations",
|
||||
"name": "QuickBooks Migrator",
|
||||
"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": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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: QuickBooks Migrator", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new QuickBooks Migrator
|
||||
() => frappe.tests.make('QuickBooks Migrator', [
|
||||
// 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 TestQuickBooksMigrator(unittest.TestCase):
|
||||
pass
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,10 +5,19 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
import frappe
|
||||
|
||||
class HealthcareServiceUnit(NestedSet):
|
||||
nsm_parent_field = 'parent_healthcare_service_unit'
|
||||
|
||||
def autoname(self):
|
||||
if self.company:
|
||||
suffix = " - " + frappe.get_cached_value('Company', self.company, "abbr")
|
||||
if not self.healthcare_service_unit_name.endswith(suffix):
|
||||
self.name = self.healthcare_service_unit_name + suffix
|
||||
else:
|
||||
self.name = self.healthcare_service_unit_name
|
||||
|
||||
def on_update(self):
|
||||
super(HealthcareServiceUnit, self).on_update()
|
||||
self.validate_one_root()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -105,7 +105,9 @@ def get_healthcare_service_unit():
|
||||
parent_service_unit.healthcare_service_unit_name = "All Healthcare Service Units"
|
||||
parent_service_unit.is_group = 1
|
||||
parent_service_unit.save(ignore_permissions = True)
|
||||
service_unit.parent_healthcare_service_unit = "All Healthcare Service Units"
|
||||
service_unit.parent_healthcare_service_unit = parent_service_unit.name
|
||||
else:
|
||||
service_unit.parent_healthcare_service_unit = service_unit_parent_name[0][0]
|
||||
service_unit.save(ignore_permissions = True)
|
||||
return service_unit.name
|
||||
return service_unit
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -142,6 +142,7 @@ frappe.ui.form.on('Patient Appointment', {
|
||||
frm.set_value('service_unit', btn_selected.attr('data-service-unit') || '');
|
||||
frm.set_value('duration', btn_selected.attr('data-duration'));
|
||||
d.hide();
|
||||
frm.enable_save();
|
||||
frm.save();
|
||||
frm.enable_save();
|
||||
}
|
||||
|
||||
@@ -339,13 +339,13 @@ def get_events(start, end, filters=None):
|
||||
|
||||
data = frappe.db.sql("""select name, patient, practitioner, status,
|
||||
duration, timestamp(appointment_date, appointment_time) as
|
||||
'appointment_date' from `tabPatient Appointment` where
|
||||
'start' from `tabPatient Appointment` where
|
||||
(appointment_date between %(start)s and %(end)s)
|
||||
and docstatus < 2 {conditions}""".format(conditions=conditions),
|
||||
{"start": start, "end": end}, as_dict=True, update={"allDay": 0})
|
||||
|
||||
for item in data:
|
||||
item.appointment_datetime = item.appointment_date + datetime.timedelta(minutes = item.duration)
|
||||
item.end = item.start + datetime.timedelta(minutes = item.duration)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@@ -10,37 +10,5 @@ frappe.views.calendar["Patient Appointment"] = {
|
||||
},
|
||||
order_by: "appointment_date",
|
||||
gantt: true,
|
||||
get_events_method: "erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_events",
|
||||
filters: [
|
||||
{
|
||||
'fieldtype': 'Link',
|
||||
'fieldname': 'practitioner',
|
||||
'options': 'Healthcare Practitioner',
|
||||
'label': __('Healthcare Practitioner')
|
||||
},
|
||||
{
|
||||
'fieldtype': 'Link',
|
||||
'fieldname': 'patient',
|
||||
'options': 'Patient',
|
||||
'label': __('Patient')
|
||||
},
|
||||
{
|
||||
'fieldtype': 'Link',
|
||||
'fieldname': 'appointment_type',
|
||||
'options': 'Appointment Type',
|
||||
'label': __('Appointment Type')
|
||||
},
|
||||
{
|
||||
'fieldtype': 'Link',
|
||||
'fieldname': 'department',
|
||||
'options': 'Medical Department',
|
||||
'label': __('Department')
|
||||
},
|
||||
{
|
||||
'fieldtype': 'Select',
|
||||
'fieldname': 'status',
|
||||
'options': 'Scheduled\nOpen\nClosed\nPending',
|
||||
'label': __('Status')
|
||||
}
|
||||
]
|
||||
get_events_method: "erpnext.healthcare.doctype.patient_appointment.patient_appointment.get_events"
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user