mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-22 18:49:40 +00:00
Compare commits
162 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b697c5298 | ||
|
|
2426d00dd6 | ||
|
|
5395b164cd | ||
|
|
047a7123eb | ||
|
|
cb1726d6ec | ||
|
|
6b78e520d2 | ||
|
|
fad08e1bcb | ||
|
|
3d58576797 | ||
|
|
438490fd29 | ||
|
|
f001a9eb4f | ||
|
|
f8a5cfe8d8 | ||
|
|
a88eaa6e20 | ||
|
|
6ff2f395f5 | ||
|
|
ccff3e2aec | ||
|
|
7f37d26f05 | ||
|
|
c704630d5f | ||
|
|
1a41929c6b | ||
|
|
a97a520aa8 | ||
|
|
3e6663d47e | ||
|
|
eeb66dfc8e | ||
|
|
59f16bc942 | ||
|
|
e77f38e7e2 | ||
|
|
598d34445f | ||
|
|
768513f2f9 | ||
|
|
dcb71a61ad | ||
|
|
3f32218bc0 | ||
|
|
b4bff7e298 | ||
|
|
41c5fda196 | ||
|
|
305c82bd8d | ||
|
|
cd11bdfdbb | ||
|
|
0c0e49a421 | ||
|
|
3f398d24f3 | ||
|
|
d9a82738d0 | ||
|
|
1f7a5dcd07 | ||
|
|
452619c668 | ||
|
|
9d0dba5569 | ||
|
|
3df1327b94 | ||
|
|
38eaaade89 | ||
|
|
2a98e59bd4 | ||
|
|
03348364e9 | ||
|
|
83fd31973f | ||
|
|
ac64b39562 | ||
|
|
c73c576536 | ||
|
|
034429b34d | ||
|
|
874866e9f9 | ||
|
|
c365ce8f21 | ||
|
|
3a11f34355 | ||
|
|
91eac5a7cf | ||
|
|
aef7a6ec44 | ||
|
|
6192d24235 | ||
|
|
24fe7286fc | ||
|
|
991c121b57 | ||
|
|
23ec18e3e4 | ||
|
|
500ddc94c7 | ||
|
|
bbd8b04012 | ||
|
|
bb1b6b42e2 | ||
|
|
8e71074e1c | ||
|
|
ff0deedca9 | ||
|
|
4bb90add1d | ||
|
|
44ec05f79b | ||
|
|
7844b79274 | ||
|
|
ea75295bb3 | ||
|
|
d2c643eb0b | ||
|
|
94fcb0e9f9 | ||
|
|
3362d6b948 | ||
|
|
75c1682e61 | ||
|
|
2dc8972794 | ||
|
|
f786eccdf9 | ||
|
|
a1036ad50b | ||
|
|
5b34d00bc0 | ||
|
|
ee3b788024 | ||
|
|
b509b06edf | ||
|
|
5fcccda883 | ||
|
|
4fb9230d16 | ||
|
|
37d3686372 | ||
|
|
5eafa5a487 | ||
|
|
97dbb4d125 | ||
|
|
17ac38ff29 | ||
|
|
65652071ff | ||
|
|
79dc8ac9cc | ||
|
|
15e7646edd | ||
|
|
d1b87ba41c | ||
|
|
a5576f5b21 | ||
|
|
8976ad5ca1 | ||
|
|
c7f8b82fff | ||
|
|
6b62b86bbf | ||
|
|
8fbf856618 | ||
|
|
7d6d678e8d | ||
|
|
c22ba2ec26 | ||
|
|
0cf0ebf08b | ||
|
|
0ff35a852a | ||
|
|
e04431ea5c | ||
|
|
fafc277666 | ||
|
|
fe1e4a41e6 | ||
|
|
7a8c5b0c2c | ||
|
|
056ecdca6a | ||
|
|
3b281a0a1b | ||
|
|
a60ab1af75 | ||
|
|
550fc695f1 | ||
|
|
013493de7a | ||
|
|
b3737c812a | ||
|
|
6d5a29af6a | ||
|
|
20d8c52d2a | ||
|
|
e11f299b21 | ||
|
|
68000c66fc | ||
|
|
3cc77b52e7 | ||
|
|
bd4348db10 | ||
|
|
4fd1cebf95 | ||
|
|
b892cc8b02 | ||
|
|
8652bce9e3 | ||
|
|
4e372a30fa | ||
|
|
df327f2974 | ||
|
|
3ccbb8f8b7 | ||
|
|
0d931e1d7d | ||
|
|
431b4fba72 | ||
|
|
fba985d49d | ||
|
|
4bd562d669 | ||
|
|
bb88e964a4 | ||
|
|
5f79479bd0 | ||
|
|
12b4096e68 | ||
|
|
1ef72c0b66 | ||
|
|
648191b9e8 | ||
|
|
624927bf0b | ||
|
|
3df2639a32 | ||
|
|
d982e8fcda | ||
|
|
af497ef669 | ||
|
|
79f3ea4094 | ||
|
|
e0a47aeb2f | ||
|
|
1516b8d54a | ||
|
|
e33047250e | ||
|
|
c4e38ffd4d | ||
|
|
be7703387d | ||
|
|
b800382abf | ||
|
|
e689a903d8 | ||
|
|
ecc6af9d2a | ||
|
|
5c5688b374 | ||
|
|
80f30094fb | ||
|
|
6fb2117767 | ||
|
|
0631aed3d9 | ||
|
|
88b0a1305f | ||
|
|
9e98fdfc6e | ||
|
|
cd6b955b99 | ||
|
|
bfd26b7084 | ||
|
|
18960c7757 | ||
|
|
9a7838265d | ||
|
|
57d3c93e6b | ||
|
|
a0b846fb88 | ||
|
|
8356d4b892 | ||
|
|
ba62013cbb | ||
|
|
59de1dae6a | ||
|
|
91cecf8eac | ||
|
|
6ec558bd59 | ||
|
|
11dd3ffdb5 | ||
|
|
f0ef673498 | ||
|
|
57d07d6b8e | ||
|
|
fc682c86c6 | ||
|
|
15f52e7b71 | ||
|
|
26bfede116 | ||
|
|
86217ca96c | ||
|
|
ae4ff5a403 | ||
|
|
0452b405f4 | ||
|
|
dc7004e083 |
@@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '10.1.45'
|
||||
__version__ = '10.1.72'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -207,10 +207,13 @@ def validate_account_number(name, account_number, company):
|
||||
@frappe.whitelist()
|
||||
def update_account_number(name, account_name, account_number=None):
|
||||
|
||||
account = frappe.db.get_value("Account", name, ["company"], as_dict=True)
|
||||
account = frappe.db.get_value("Account", name, "company", as_dict=True)
|
||||
if not account: return
|
||||
validate_account_number(name, account_number, account.company)
|
||||
if account_number:
|
||||
frappe.db.set_value("Account", name, "account_number", account_number.strip())
|
||||
else:
|
||||
frappe.db.set_value("Account", name, "account_number", "")
|
||||
frappe.db.set_value("Account", name, "account_name", account_name.strip())
|
||||
|
||||
new_name = get_account_autoname(account_number, account_name, account.company)
|
||||
|
||||
@@ -27,13 +27,21 @@ class Budget(Document):
|
||||
def validate_duplicate(self):
|
||||
budget_against_field = frappe.scrub(self.budget_against)
|
||||
budget_against = self.get(budget_against_field)
|
||||
existing_budget = frappe.db.get_value("Budget", {budget_against_field: budget_against,
|
||||
"fiscal_year": self.fiscal_year, "company": self.company,
|
||||
"name": ["!=", self.name], "docstatus": ["!=", 2]})
|
||||
if existing_budget:
|
||||
frappe.throw(_("Another Budget record '{0}' already exists against {1} '{2}' for fiscal year {3}")
|
||||
.format(existing_budget, self.budget_against, budget_against, self.fiscal_year), DuplicateBudgetError)
|
||||
|
||||
|
||||
accounts = [d.account for d in self.accounts] or []
|
||||
existing_budget = frappe.db.sql("""
|
||||
select
|
||||
b.name, ba.account from `tabBudget` b, `tabBudget Account` ba
|
||||
where
|
||||
ba.parent = b.name and b.docstatus < 2 and b.company = %s and %s=%s and
|
||||
b.fiscal_year=%s and b.name != %sand ba.account in (%s) """
|
||||
% ('%s', budget_against_field, '%s', '%s', '%s', ','.join(['%s'] * len(accounts))),
|
||||
(self.company, budget_against, self.fiscal_year, self.name) + tuple(accounts), as_dict=1)
|
||||
|
||||
for d in existing_budget:
|
||||
frappe.throw(_("Another Budget record '{0}' already exists against {1} '{2}' and account '{3}' for fiscal year {4}")
|
||||
.format(d.name, self.budget_against, budget_against, d.account, self.fiscal_year), DuplicateBudgetError)
|
||||
|
||||
def validate_accounts(self):
|
||||
account_list = []
|
||||
for d in self.get('accounts'):
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
@@ -702,7 +702,7 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
@@ -718,7 +718,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-20 12:40:09.611951",
|
||||
"modified": "2018-08-10 16:16:53.019380",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GL Entry",
|
||||
@@ -794,4 +794,4 @@
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
}
|
||||
}
|
||||
@@ -381,7 +381,7 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
@@ -1443,7 +1443,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2017-08-31 11:21:09.442695",
|
||||
"modified": "2018-08-10 16:35:31.361030",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry",
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
@@ -661,7 +661,7 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -795,7 +795,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-07 19:54:19.851534",
|
||||
"modified": "2018-08-10 16:35:42.833549",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry Account",
|
||||
|
||||
@@ -791,15 +791,25 @@ frappe.ui.form.on('Payment Entry', {
|
||||
var write_off_row = $.map(frm.doc["deductions"] || [], function(t) {
|
||||
return t.account==r.message[account] ? t : null; });
|
||||
|
||||
if (!write_off_row.length) {
|
||||
var row = frm.add_child("deductions");
|
||||
var row = [];
|
||||
|
||||
var difference_amount = flt(frm.doc.difference_amount,
|
||||
precision("difference_amount"));
|
||||
|
||||
if (!write_off_row.length && difference_amount) {
|
||||
row = frm.add_child("deductions");
|
||||
row.account = r.message[account];
|
||||
row.cost_center = r.message["cost_center"];
|
||||
} else {
|
||||
var row = write_off_row[0];
|
||||
row = write_off_row[0];
|
||||
}
|
||||
|
||||
if (row) {
|
||||
row.amount = flt(row.amount) + difference_amount;
|
||||
} else {
|
||||
frappe.msgprint(__("No gain or loss in the exchange rate"))
|
||||
}
|
||||
|
||||
row.amount = flt(row.amount) + flt(frm.doc.difference_amount);
|
||||
refresh_field("deductions");
|
||||
|
||||
frm.events.set_unallocated_amount(frm);
|
||||
|
||||
@@ -286,7 +286,7 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
@@ -1439,7 +1439,7 @@
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
@@ -1791,7 +1791,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-27 01:49:24.720317",
|
||||
"modified": "2018-08-10 16:34:46.771275",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Entry",
|
||||
|
||||
@@ -185,7 +185,8 @@ def get_pricing_rule_for_item(args):
|
||||
"discount_percentage": 0.0
|
||||
})
|
||||
else:
|
||||
item_details.discount_percentage = pricing_rule.discount_percentage or args.discount_percentage
|
||||
item_details.discount_percentage = (pricing_rule.get('discount_percentage', 0)
|
||||
if pricing_rule else args.discount_percentage)
|
||||
elif args.get('pricing_rule'):
|
||||
item_details = remove_pricing_rule_for_item(args.get("pricing_rule"), item_details)
|
||||
|
||||
|
||||
@@ -21,8 +21,6 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
||||
if(!this.frm.doc.supplier && this.frm.doc.credit_to) {
|
||||
this.frm.set_df_property("credit_to", "print_hide", 0);
|
||||
}
|
||||
} else {
|
||||
this.frm.set_value("disable_rounded_total", cint(frappe.sys_defaults.disable_rounded_total));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -363,7 +363,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,
|
||||
@@ -388,16 +391,20 @@ class PurchaseInvoice(BuyingController):
|
||||
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
|
||||
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({
|
||||
@@ -469,6 +476,36 @@ class PurchaseInvoice(BuyingController):
|
||||
self.negative_expense_to_be_booked += flt(item.item_tax_amount, \
|
||||
item.precision("item_tax_amount"))
|
||||
|
||||
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 = {}
|
||||
|
||||
@@ -585,6 +585,38 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "discount_percentage",
|
||||
"fieldname": "discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Discount Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -2156,7 +2188,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-30 14:21:00.962126",
|
||||
"modified": "2018-08-06 05:17:38.205356",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Item",
|
||||
|
||||
@@ -506,7 +506,7 @@ def save_invoice(doc, name, name_list):
|
||||
frappe.db.commit()
|
||||
name_list.append(name)
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback())
|
||||
frappe.db.rollback()
|
||||
frappe.log_error(frappe.get_traceback())
|
||||
|
||||
return name_list
|
||||
|
||||
@@ -589,9 +589,6 @@ class SalesInvoice(SellingController):
|
||||
def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
|
||||
auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
|
||||
|
||||
if not self.grand_total:
|
||||
return
|
||||
|
||||
if not gl_entries:
|
||||
gl_entries = self.get_gl_entries()
|
||||
|
||||
@@ -641,7 +638,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,
|
||||
@@ -669,9 +668,11 @@ class SalesInvoice(SellingController):
|
||||
self.get_gl_dict({
|
||||
"account": tax.account_head,
|
||||
"against": self.customer,
|
||||
"credit": flt(tax.base_tax_amount_after_discount_amount),
|
||||
"credit_in_account_currency": flt(tax.base_tax_amount_after_discount_amount) \
|
||||
if account_currency==self.company_currency else flt(tax.tax_amount_after_discount_amount),
|
||||
"credit": flt(tax.base_tax_amount_after_discount_amount,
|
||||
tax.precision("tax_amount_after_discount_amount")),
|
||||
"credit_in_account_currency": (flt(tax.base_tax_amount_after_discount_amount,
|
||||
tax.precision("base_tax_amount_after_discount_amount")) if account_currency==self.company_currency else
|
||||
flt(tax.tax_amount_after_discount_amount, tax.precision("tax_amount_after_discount_amount"))),
|
||||
"cost_center": tax.cost_center
|
||||
}, account_currency)
|
||||
)
|
||||
@@ -679,7 +680,7 @@ class SalesInvoice(SellingController):
|
||||
def make_item_gl_entries(self, gl_entries):
|
||||
# income account gl entries
|
||||
for item in self.get("items"):
|
||||
if flt(item.base_net_amount):
|
||||
if flt(item.base_net_amount, item.precision("base_net_amount")):
|
||||
if item.is_fixed_asset:
|
||||
asset = frappe.get_doc("Asset", item.asset)
|
||||
|
||||
@@ -696,9 +697,10 @@ class SalesInvoice(SellingController):
|
||||
self.get_gl_dict({
|
||||
"account": item.income_account,
|
||||
"against": self.customer,
|
||||
"credit": item.base_net_amount,
|
||||
"credit_in_account_currency": item.base_net_amount \
|
||||
if account_currency==self.company_currency else item.net_amount,
|
||||
"credit": flt(item.base_net_amount, item.precision("base_net_amount")),
|
||||
"credit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount"))
|
||||
if account_currency==self.company_currency
|
||||
else flt(item.net_amount, item.precision("net_amount"))),
|
||||
"cost_center": item.cost_center
|
||||
}, account_currency)
|
||||
)
|
||||
@@ -769,7 +771,7 @@ class SalesInvoice(SellingController):
|
||||
|
||||
def make_write_off_gl_entry(self, gl_entries):
|
||||
# write off entries, applicable if only pos
|
||||
if self.write_off_account and self.write_off_amount:
|
||||
if self.write_off_account and flt(self.write_off_amount, self.precision("write_off_amount")):
|
||||
write_off_account_currency = get_account_currency(self.write_off_account)
|
||||
default_cost_center = frappe.db.get_value('Company', self.company, 'cost_center')
|
||||
|
||||
@@ -779,9 +781,10 @@ class SalesInvoice(SellingController):
|
||||
"party_type": "Customer",
|
||||
"party": self.customer,
|
||||
"against": self.write_off_account,
|
||||
"credit": self.base_write_off_amount,
|
||||
"credit_in_account_currency": self.base_write_off_amount \
|
||||
if self.party_account_currency==self.company_currency else self.write_off_amount,
|
||||
"credit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")),
|
||||
"credit_in_account_currency": (flt(self.base_write_off_amount,
|
||||
self.precision("base_write_off_amount")) if self.party_account_currency==self.company_currency
|
||||
else flt(self.write_off_amount, self.precision("write_off_amount"))),
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype
|
||||
}, self.party_account_currency)
|
||||
@@ -790,15 +793,16 @@ class SalesInvoice(SellingController):
|
||||
self.get_gl_dict({
|
||||
"account": self.write_off_account,
|
||||
"against": self.customer,
|
||||
"debit": self.base_write_off_amount,
|
||||
"debit_in_account_currency": self.base_write_off_amount \
|
||||
if write_off_account_currency==self.company_currency else self.write_off_amount,
|
||||
"debit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")),
|
||||
"debit_in_account_currency": (flt(self.base_write_off_amount,
|
||||
self.precision("base_write_off_amount")) if write_off_account_currency==self.company_currency
|
||||
else flt(self.write_off_amount, self.precision("write_off_amount"))),
|
||||
"cost_center": self.write_off_cost_center or default_cost_center
|
||||
}, write_off_account_currency)
|
||||
)
|
||||
|
||||
def make_gle_for_rounding_adjustment(self, gl_entries):
|
||||
if self.rounding_adjustment:
|
||||
if flt(self.rounding_adjustment, self.precision("rounding_adjustment")):
|
||||
round_off_account, round_off_cost_center = \
|
||||
get_round_off_account_and_cost_center(self.company)
|
||||
|
||||
@@ -806,8 +810,10 @@ class SalesInvoice(SellingController):
|
||||
self.get_gl_dict({
|
||||
"account": round_off_account,
|
||||
"against": self.customer,
|
||||
"credit_in_account_currency": self.rounding_adjustment,
|
||||
"credit": self.base_rounding_adjustment,
|
||||
"credit_in_account_currency": flt(self.rounding_adjustment,
|
||||
self.precision("rounding_adjustment")),
|
||||
"credit": flt(self.base_rounding_adjustment,
|
||||
self.precision("base_rounding_adjustment")),
|
||||
"cost_center": round_off_cost_center,
|
||||
}
|
||||
))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,7 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
"fieldname":"ageing_based_on",
|
||||
"label": __("Ageing Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": 'Posting Date\nDue Date',
|
||||
"options": 'Posting Date\nDue Date\nSupplier Invoice Date',
|
||||
"default": "Posting Date"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<td class="text-right">{%= format_currency(balance_row[range3]) %}</td>
|
||||
<td class="text-right">{%= format_currency(balance_row[range4]) %}</td>
|
||||
<td class="text-right">
|
||||
{%= format_currency(flt(balance_row[__("Outstanding Amount")]), data[data.length-1]["currency"]) %}
|
||||
{%= format_currency(flt(balance_row[("outstanding_amount")]), data[data.length-1]["currency"]) %}
|
||||
</td>
|
||||
</tr>
|
||||
<td>{%= __("PDC/LC") %}</td>
|
||||
@@ -84,7 +84,7 @@
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="text-right">
|
||||
{%= format_currency(flt(balance_row[__("PDC/LC Amount")]), data[data.length-1]["currency"]) %}
|
||||
{%= format_currency(flt(balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}
|
||||
</td>
|
||||
<tr class="cvs-footer">
|
||||
<th class="text-left">{%= __("Cheques Required") %}</th>
|
||||
@@ -93,7 +93,7 @@
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th class="text-right">
|
||||
{%= format_currency(flt(balance_row[__("Outstanding Amount")]-balance_row[__("PDC/LC Amount")]), data[data.length-1]["currency"]) %}</th>
|
||||
{%= format_currency(flt(balance_row[("outstanding_amount")]-balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -161,26 +161,26 @@
|
||||
</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>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("PDC/LC Amount")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("Remaining Balance")], data[i]["currency"]) %}</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>
|
||||
<td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>
|
||||
{% } %}
|
||||
{% } else { %}
|
||||
<td></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") { %}
|
||||
@@ -205,9 +205,9 @@
|
||||
{%= data[i][__("Customer LPO")] %}</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>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("PDC/LC Amount")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("Remaining Balance")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= data[i][("pdc/lc_ref")] %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>
|
||||
{% } %}
|
||||
{% } %}
|
||||
{% } else { %}
|
||||
@@ -228,14 +228,14 @@
|
||||
{% } else { %}
|
||||
<td><b>{%= __("Total") %}</b></td>
|
||||
{% } %}
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("Total Invoiced Amt")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("Total Paid Amt")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][("total_invoiced_amt")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][("total_paid_amt")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= report.report_name === "Accounts Receivable Summary" ? format_currency(data[i][__("Credit Note Amt")], data[i]["currency"]) : format_currency(data[i][__("Debit Note Amt")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("Total Outstanding Amt")], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][("total_outstanding_amt")], data[i]["currency"]) %}</td>
|
||||
{% } %}
|
||||
{% } %}
|
||||
</tr>
|
||||
{% } %}
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="text-right text-muted">{{ __("Printed On ") }}{%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
|
||||
<p class="text-right text-muted">{{ __("Printed On ") }}{%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
|
||||
|
||||
@@ -60,6 +60,7 @@ class ReceivablePayableReport(object):
|
||||
for label in ("Invoiced Amount", "Paid Amount", credit_or_debit_note, "Outstanding Amount"):
|
||||
columns.append({
|
||||
"label": label,
|
||||
"fieldname": frappe.scrub(label),
|
||||
"fieldtype": "Currency",
|
||||
"options": "currency",
|
||||
"width": 120
|
||||
@@ -87,25 +88,49 @@ class ReceivablePayableReport(object):
|
||||
"width": 120
|
||||
})
|
||||
|
||||
columns.append({
|
||||
columns += [
|
||||
{
|
||||
"fieldname": "currency",
|
||||
"label": _("Currency"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Currency",
|
||||
"width": 100
|
||||
})
|
||||
|
||||
columns += [
|
||||
_("PDC/LC Date") + ":Date:110",
|
||||
_("PDC/LC Ref") + ":Data:110",
|
||||
_("PDC/LC Amount") + ":Currency/currency:130",
|
||||
_("Remaining Balance") + ":Currency/currency:130"
|
||||
]
|
||||
},
|
||||
{
|
||||
"fieldname": "pdc/lc_date",
|
||||
"label": _("PDC/LC Date"),
|
||||
"fieldtype": "Date",
|
||||
"width": 110
|
||||
},
|
||||
{
|
||||
"fieldname": "pdc/lc_ref",
|
||||
"label": _("PDC/LC Ref"),
|
||||
"fieldtype": "Data",
|
||||
"width": 110
|
||||
},
|
||||
{
|
||||
"fieldname": "pdc/lc_amount",
|
||||
"label": _("PDC/LC Amount"),
|
||||
"fieldtype": "Currency",
|
||||
"options": "Currency",
|
||||
"width": 130
|
||||
},
|
||||
{
|
||||
"fieldname": "remaining_balance",
|
||||
"label": _("Remaining Balance"),
|
||||
"fieldtype": "Currency",
|
||||
"options": "Currency",
|
||||
"width": 130
|
||||
}]
|
||||
|
||||
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",
|
||||
@@ -123,9 +148,6 @@ class ReceivablePayableReport(object):
|
||||
currency_precision = get_currency_precision() or 2
|
||||
dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
|
||||
|
||||
dn_details = get_dn_details(args.get("party_type"))
|
||||
voucher_details = self.get_voucher_details(args.get("party_type"), dn_details)
|
||||
|
||||
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
|
||||
|
||||
if not self.filters.get("company"):
|
||||
@@ -137,8 +159,14 @@ class ReceivablePayableReport(object):
|
||||
|
||||
data = []
|
||||
pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date)
|
||||
gl_entries_data = self.get_entries_till(self.filters.report_date, args.get("party_type"))
|
||||
|
||||
for gle in self.get_entries_till(self.filters.report_date, args.get("party_type")):
|
||||
if gl_entries_data:
|
||||
voucher_nos = [d.voucher_no for d in gl_entries_data] or []
|
||||
dn_details = get_dn_details(args.get("party_type"), voucher_nos)
|
||||
voucher_details = get_voucher_details(args.get("party_type"), voucher_nos, dn_details)
|
||||
|
||||
for gle in gl_entries_data:
|
||||
if self.is_receivable_or_payable(gle, dr_or_cr, future_vouchers):
|
||||
outstanding_amount, credit_note_amount = self.get_outstanding_amount(gle,
|
||||
self.filters.report_date, dr_or_cr, return_entries, currency_precision)
|
||||
@@ -151,6 +179,7 @@ class ReceivablePayableReport(object):
|
||||
|
||||
# get due date
|
||||
due_date = voucher_details.get(gle.voucher_no, {}).get("due_date", "")
|
||||
bill_date = voucher_details.get(gle.voucher_no, {}).get("bill_date", "")
|
||||
|
||||
row += [gle.voucher_type, gle.voucher_no, due_date]
|
||||
|
||||
@@ -167,15 +196,25 @@ class ReceivablePayableReport(object):
|
||||
row += [invoiced_amount, paid_amt, credit_note_amount, outstanding_amount]
|
||||
|
||||
# ageing data
|
||||
entry_date = due_date if self.filters.ageing_based_on == "Due Date" else gle.posting_date
|
||||
if self.filters.ageing_based_on == "Due Date":
|
||||
entry_date = due_date
|
||||
elif self.filters.ageing_based_on == "Supplier Invoice Date":
|
||||
entry_date = bill_date
|
||||
else:
|
||||
entry_date = gle.posting_date
|
||||
row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2),
|
||||
cint(self.filters.range3), self.age_as_on, entry_date, outstanding_amount)
|
||||
|
||||
|
||||
# issue 6371-Ageing buckets should not have amounts if due date is not reached
|
||||
if self.filters.ageing_based_on == "Due Date" \
|
||||
and getdate(due_date) > getdate(self.filters.report_date):
|
||||
row[-1]=row[-2]=row[-3]=row[-4]=0
|
||||
|
||||
if self.filters.ageing_based_on == "Supplier Invoice Date" \
|
||||
and getdate(bill_date) > getdate(self.filters.report_date):
|
||||
row[-1]=row[-2]=row[-3]=row[-4]=0
|
||||
|
||||
if self.filters.get(scrub(args.get("party_type"))):
|
||||
row.append(gle.account_currency)
|
||||
else:
|
||||
@@ -207,12 +246,11 @@ class ReceivablePayableReport(object):
|
||||
|
||||
def get_entries_after(self, report_date, party_type):
|
||||
# returns a distinct list
|
||||
return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries(party_type)
|
||||
if getdate(e.posting_date) > report_date]))
|
||||
return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries(party_type, report_date, for_future=True)]))
|
||||
|
||||
def get_entries_till(self, report_date, party_type):
|
||||
# returns a generator
|
||||
return (e for e in self.get_gl_entries(party_type) if getdate(e.posting_date) <= report_date)
|
||||
return self.get_gl_entries(party_type, report_date)
|
||||
|
||||
def is_receivable_or_payable(self, gle, dr_or_cr, future_vouchers):
|
||||
return (
|
||||
@@ -239,14 +277,16 @@ class ReceivablePayableReport(object):
|
||||
|
||||
for e in self.get_gl_entries_for(gle.party, gle.party_type, gle.voucher_type, gle.voucher_no):
|
||||
if getdate(e.posting_date) <= report_date and e.name!=gle.name:
|
||||
amount = flt(e.get(reverse_dr_or_cr)) - flt(e.get(dr_or_cr))
|
||||
amount = flt(e.get(reverse_dr_or_cr), currency_precision) - flt(e.get(dr_or_cr), currency_precision)
|
||||
if e.voucher_no not in return_entries:
|
||||
payment_amount += amount
|
||||
else:
|
||||
credit_note_amount += amount
|
||||
|
||||
outstanding_amount = flt((flt(gle.get(dr_or_cr)) - flt(gle.get(reverse_dr_or_cr)) \
|
||||
- payment_amount - credit_note_amount), currency_precision)
|
||||
outstanding_amount = (flt((flt(gle.get(dr_or_cr), currency_precision)
|
||||
- flt(gle.get(reverse_dr_or_cr), currency_precision)
|
||||
- payment_amount - credit_note_amount), currency_precision))
|
||||
|
||||
credit_note_amount = flt(credit_note_amount, currency_precision)
|
||||
|
||||
return outstanding_amount, credit_note_amount
|
||||
@@ -275,42 +315,31 @@ class ReceivablePayableReport(object):
|
||||
|
||||
return self.party_map
|
||||
|
||||
def get_voucher_details(self, party_type, dn_details):
|
||||
voucher_details = frappe._dict()
|
||||
def get_gl_entries(self, party_type, date=None, for_future=False):
|
||||
conditions, values = self.prepare_conditions(party_type)
|
||||
|
||||
if party_type == "Customer":
|
||||
for si in frappe.db.sql("""select name, due_date, po_no
|
||||
from `tabSales Invoice` where docstatus=1""", as_dict=1):
|
||||
si['delivery_note'] = dn_details.get(si.name)
|
||||
voucher_details.setdefault(si.name, si)
|
||||
if self.filters.get(scrub(party_type)):
|
||||
select_fields = "sum(debit_in_account_currency) as debit, sum(credit_in_account_currency) as credit"
|
||||
else:
|
||||
select_fields = "sum(debit) as debit, sum(credit) as credit"
|
||||
|
||||
if party_type == "Supplier":
|
||||
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
|
||||
from `tabPurchase Invoice` where docstatus = 1
|
||||
union
|
||||
select name, due_date, bill_no, bill_date from `tabJournal Entry`
|
||||
where docstatus = 1 and bill_no is not NULL""", as_dict=1):
|
||||
voucher_details.setdefault(pi.name, pi)
|
||||
if date and not for_future:
|
||||
conditions += " and posting_date <= '%s'" % date
|
||||
|
||||
return voucher_details
|
||||
if date and for_future:
|
||||
conditions += " and posting_date > '%s'" % date
|
||||
|
||||
def get_gl_entries(self, party_type):
|
||||
if not hasattr(self, "gl_entries"):
|
||||
conditions, values = self.prepare_conditions(party_type)
|
||||
|
||||
if self.filters.get(scrub(party_type)):
|
||||
select_fields = "sum(debit_in_account_currency) as debit, sum(credit_in_account_currency) as credit"
|
||||
else:
|
||||
select_fields = "sum(debit) as debit, sum(credit) as credit"
|
||||
|
||||
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
|
||||
voucher_type, voucher_no, against_voucher_type, against_voucher,
|
||||
account_currency, remarks, {0}
|
||||
from `tabGL Entry`
|
||||
where docstatus < 2 and party_type=%s and (party is not null and party != '') {1}
|
||||
self.gl_entries = frappe.db.sql("""
|
||||
select
|
||||
name, posting_date, account, party_type, party, voucher_type, voucher_no,
|
||||
against_voucher_type, against_voucher, account_currency, remarks, {0}
|
||||
from
|
||||
`tabGL Entry`
|
||||
where
|
||||
docstatus < 2 and party_type=%s and (party is not null and party != '') {1}
|
||||
group by voucher_type, voucher_no, against_voucher_type, against_voucher, party
|
||||
order by posting_date, party"""
|
||||
.format(select_fields, conditions), values, as_dict=True)
|
||||
.format(select_fields, conditions), values, as_dict=True)
|
||||
|
||||
return self.gl_entries
|
||||
|
||||
@@ -419,7 +448,6 @@ def get_pdc_details(party_type, report_date):
|
||||
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)
|
||||
|
||||
if scrub(party_type):
|
||||
amount_field = ("jea.debit_in_account_currency"
|
||||
if party_type == 'Supplier' else "jea.credit_in_account_currency")
|
||||
@@ -446,18 +474,57 @@ def get_pdc_details(party_type, report_date):
|
||||
|
||||
return pdc_details
|
||||
|
||||
def get_dn_details(party_type):
|
||||
def get_dn_details(party_type, voucher_nos):
|
||||
dn_details = frappe._dict()
|
||||
|
||||
if party_type == "Customer":
|
||||
for si in frappe.db.sql("""select parent, GROUP_CONCAT(delivery_note SEPARATOR ', ') as dn
|
||||
from `tabSales Invoice Item`
|
||||
where docstatus=1 and delivery_note is not null and delivery_note != '' group by parent
|
||||
Union
|
||||
select against_sales_invoice as parent, GROUP_CONCAT(parent SEPARATOR ', ') as dn
|
||||
from `tabDelivery Note Item`
|
||||
where docstatus=1 and against_sales_invoice is not null
|
||||
and against_sales_invoice != '' group by against_sales_invoice""", as_dict=1):
|
||||
for si in frappe.db.sql("""
|
||||
select
|
||||
parent, GROUP_CONCAT(delivery_note SEPARATOR ', ') as dn
|
||||
from
|
||||
`tabSales Invoice Item`
|
||||
where
|
||||
docstatus=1 and delivery_note is not null and delivery_note != ''
|
||||
and parent in (%s) group by parent
|
||||
""" %(','.join(['%s'] * len(voucher_nos))), tuple(voucher_nos) , as_dict=1):
|
||||
dn_details.setdefault(si.parent, si.dn)
|
||||
|
||||
for si in frappe.db.sql("""
|
||||
select
|
||||
against_sales_invoice as parent, GROUP_CONCAT(parent SEPARATOR ', ') as dn
|
||||
from
|
||||
`tabDelivery Note Item`
|
||||
where
|
||||
docstatus=1 and against_sales_invoice is not null and against_sales_invoice != ''
|
||||
and against_sales_invoice in (%s)
|
||||
group by against_sales_invoice
|
||||
""" %(','.join(['%s'] * len(voucher_nos))), tuple(voucher_nos) , as_dict=1):
|
||||
if si.parent in dn_details:
|
||||
dn_details[si.parent] += ', %s' %(si.dn)
|
||||
else:
|
||||
dn_details.setdefault(si.parent, si.dn)
|
||||
|
||||
return dn_details
|
||||
|
||||
def get_voucher_details(party_type, voucher_nos, dn_details):
|
||||
voucher_details = frappe._dict()
|
||||
|
||||
if party_type == "Customer":
|
||||
for si in frappe.db.sql("""select name, due_date, po_no
|
||||
from `tabSales Invoice` where docstatus=1 and name in (%s)
|
||||
""" %(','.join(['%s'] *len(voucher_nos))), (tuple(voucher_nos)), as_dict=1):
|
||||
si['delivery_note'] = dn_details.get(si.name)
|
||||
voucher_details.setdefault(si.name, si)
|
||||
|
||||
if party_type == "Supplier":
|
||||
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
|
||||
from `tabPurchase Invoice` where docstatus = 1 and name in (%s)
|
||||
""" %(','.join(['%s'] *len(voucher_nos))), (tuple(voucher_nos)), as_dict=1):
|
||||
voucher_details.setdefault(pi.name, pi)
|
||||
|
||||
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date from
|
||||
`tabJournal Entry` where docstatus = 1 and bill_no is not NULL and name in (%s)
|
||||
""" %(','.join(['%s'] *len(voucher_nos))), (tuple(voucher_nos)), as_dict=1):
|
||||
voucher_details.setdefault(pi.name, pi)
|
||||
|
||||
return voucher_details
|
||||
|
||||
@@ -3,47 +3,75 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
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,
|
||||
a.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)
|
||||
|
||||
return data
|
||||
|
||||
def get_filter_conditions(filters):
|
||||
conditions = ""
|
||||
|
||||
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"):
|
||||
conditions += " and a.name = %(asset)s"
|
||||
|
||||
filters_data.append(["against_voucher", "=", filters.get("asset")])
|
||||
|
||||
if filters.get("asset_category"):
|
||||
conditions += " and a.asset_category = %(asset_category)s"
|
||||
|
||||
return conditions
|
||||
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])
|
||||
|
||||
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_assets_details(assets):
|
||||
assets_details = {}
|
||||
|
||||
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
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -306,19 +306,20 @@ def set_gl_entries_by_account(company, from_date, to_date, root_lft, root_rgt, f
|
||||
|
||||
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 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
|
||||
},
|
||||
as_dict=True)
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
||||
if not filters: filters = {}
|
||||
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:
|
||||
@@ -54,7 +54,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
||||
]
|
||||
|
||||
row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount] \
|
||||
if d.stock_uom != d.uom else [d.base_net_rate, d.base_net_amount]
|
||||
if d.stock_uom != d.uom and d.stock_qty != 0 else [d.base_net_rate, d.base_net_amount]
|
||||
|
||||
total_tax = 0
|
||||
for tax in tax_columns:
|
||||
@@ -223,13 +223,13 @@ def get_tax_accounts(item_list, columns, company_currency,
|
||||
item_tax_amount = flt((tax_amount * d.base_net_amount) / item_net_amount) \
|
||||
if item_net_amount else 0
|
||||
if item_tax_amount:
|
||||
tax_amount = flt(item_tax_amount, tax_amount_precision)
|
||||
tax_amount = (tax_amount * -1
|
||||
if (doctype == 'Purchase Invoice' and name in deducted_tax) else tax_amount)
|
||||
tax_value = flt(item_tax_amount, tax_amount_precision)
|
||||
tax_value = (tax_value * -1
|
||||
if (doctype == 'Purchase Invoice' and name in deducted_tax) else tax_value)
|
||||
|
||||
itemised_tax.setdefault(d.name, {})[description] = frappe._dict({
|
||||
"tax_rate": tax_rate,
|
||||
"tax_amount": tax_amount
|
||||
"tax_amount": tax_value
|
||||
})
|
||||
|
||||
except ValueError:
|
||||
|
||||
@@ -67,11 +67,33 @@ frappe.ui.form.on('Asset', {
|
||||
frm.trigger("create_asset_maintenance");
|
||||
}, __("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");
|
||||
}
|
||||
},
|
||||
|
||||
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];
|
||||
|
||||
@@ -283,3 +283,34 @@ def get_item_details(item_code):
|
||||
})
|
||||
|
||||
return ret
|
||||
|
||||
@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
|
||||
@@ -5,13 +5,13 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt, today, getdate
|
||||
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):
|
||||
|
||||
@@ -22,7 +22,7 @@ frappe.ui.form.on('Asset Category', {
|
||||
var d = locals[cdt][cdn];
|
||||
return {
|
||||
"filters": {
|
||||
"root_type": "Asset",
|
||||
"account_type": "Accumulated Depreciation",
|
||||
"is_group": 0,
|
||||
"company": d.company_name
|
||||
}
|
||||
@@ -41,4 +41,4 @@ frappe.ui.form.on('Asset Category', {
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2378,6 +2378,37 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rounded_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Rounded Total",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -2409,6 +2440,36 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "disable_rounded_total",
|
||||
"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": "Disable Rounded Total",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -3293,7 +3354,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-18 07:49:53.131408",
|
||||
"modified": "2018-08-01 15:18:33.155409",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
||||
@@ -629,6 +629,38 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "discount_percentage",
|
||||
"fieldname": "discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Discount Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -1897,7 +1929,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-18 07:53:54.677844",
|
||||
"modified": "2018-08-06 05:16:58.258276",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order Item",
|
||||
|
||||
@@ -1983,6 +1983,37 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rounded_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Rounded Total",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -2014,6 +2045,36 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "disable_rounded_total",
|
||||
"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": "Disable Rounded Total",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -2177,65 +2238,65 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "group_same_items",
|
||||
"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": "Group same items",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"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,
|
||||
"fieldname": "group_same_items",
|
||||
"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": "Group same items",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_72",
|
||||
"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,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_72",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "letter_head",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -2549,7 +2610,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2018-07-06 02:45:48.616334",
|
||||
"modified": "2018-08-01 15:18:23.265621",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -470,6 +470,38 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "discount_percentage",
|
||||
"fieldname": "discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Discount Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -1645,7 +1677,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-01-25 15:04:40.171617",
|
||||
"modified": "2018-08-06 05:33:07.404385",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation Item",
|
||||
|
||||
@@ -291,14 +291,6 @@ def get_data():
|
||||
"label": _("Healthcare"),
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"module_name": "Hub",
|
||||
"color": "#009248",
|
||||
"icon": "/assets/erpnext/images/hub_logo.svg",
|
||||
"type": "page",
|
||||
"link": "hub",
|
||||
"label": _("Hub")
|
||||
},
|
||||
{
|
||||
"module_name": "Data Import",
|
||||
"color": "#FFF168",
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
source_link = "https://github.com/frappe/erpnext"
|
||||
source_link = "https://github.com/erpnext/foundation"
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return [
|
||||
{
|
||||
"label": _("Setup"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Hub Settings"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": _("Hub"),
|
||||
"items": [
|
||||
{
|
||||
"type": "page",
|
||||
"name": "hub"
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
@@ -99,9 +99,16 @@ class BuyingController(StockController):
|
||||
def set_total_in_words(self):
|
||||
from frappe.utils import money_in_words
|
||||
if self.meta.get_field("base_in_words"):
|
||||
self.base_in_words = money_in_words(self.base_grand_total, self.company_currency)
|
||||
amount = (self.base_rounded_total
|
||||
if not self.get("disable_rounded_total") else self.base_grand_total)
|
||||
|
||||
self.base_in_words = money_in_words(amount, self.company_currency)
|
||||
|
||||
if self.meta.get_field("in_words"):
|
||||
self.in_words = money_in_words(self.grand_total, self.currency)
|
||||
amount = (self.rounded_total
|
||||
if not self.get("disable_rounded_total") else self.grand_total)
|
||||
|
||||
self.in_words = money_in_words(amount, self.currency)
|
||||
|
||||
# update valuation rate
|
||||
def update_valuation_rate(self, parentfield):
|
||||
|
||||
@@ -218,7 +218,8 @@ def bom(doctype, txt, searchfield, start, page_len, filters):
|
||||
def get_project_name(doctype, txt, searchfield, start, page_len, filters):
|
||||
cond = ''
|
||||
if filters.get('customer'):
|
||||
cond = '(`tabProject`.customer = "' + filters['customer'] + '" or ifnull(`tabProject`.customer,"")="") and'
|
||||
cond = """(`tabProject`.customer = '%s' or
|
||||
ifnull(`tabProject`.customer,"")="") and""" %(frappe.db.escape(filters.get("customer")))
|
||||
|
||||
return frappe.db.sql("""select `tabProject`.name from `tabProject`
|
||||
where `tabProject`.status not in ("Completed", "Cancelled")
|
||||
|
||||
@@ -139,7 +139,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
|
||||
@@ -151,6 +151,7 @@ def get_ref_item_dict(valid_items, ref_item_row):
|
||||
"rejected_qty": 0,
|
||||
"received_qty": 0,
|
||||
"serial_no": [],
|
||||
"conversion_factor": ref_item_row.get("conversion_factor", 1),
|
||||
"batch_no": []
|
||||
}))
|
||||
item_dict = valid_items[ref_item_row.item_code]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "RES.######",
|
||||
"beta": 0,
|
||||
@@ -662,7 +662,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-01-09 14:14:30.090317",
|
||||
"modified": "2018-08-20 11:21:19.248393",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Education",
|
||||
"name": "Assessment Result",
|
||||
|
||||
@@ -33,7 +33,7 @@ class StudentGroup(Document):
|
||||
program_enrollment = get_program_enrollment(self.academic_year, self.academic_term, self.program, self.batch, self.course)
|
||||
students = [d.student for d in program_enrollment] if program_enrollment else []
|
||||
for d in self.students:
|
||||
if not frappe.db.get_value("Student", d.student, "enabled") and d.active:
|
||||
if not frappe.db.get_value("Student", d.student, "enabled") and d.active and not self.disabled:
|
||||
frappe.throw(_("{0} - {1} is inactive student".format(d.group_roll_number, d.student_name)))
|
||||
|
||||
if (self.group_based_on == "Batch") and cint(frappe.defaults.get_defaults().validate_batch)\
|
||||
|
||||
@@ -73,6 +73,7 @@ def get_attendance_list(from_date, to_date, student_group, students_list):
|
||||
return att_map
|
||||
|
||||
def get_students_with_leave_application(from_date, to_date, students_list):
|
||||
if not students_list: return
|
||||
leave_applications = frappe.db.sql("""
|
||||
select student, from_date, to_date
|
||||
from `tabStudent Leave Application`
|
||||
|
||||
@@ -34,7 +34,7 @@ class LabTestTemplate(Document):
|
||||
# remove template refernce from item and disable item
|
||||
if(self.item):
|
||||
try:
|
||||
frappe.delete_doc("Item",self.item)
|
||||
frappe.delete_doc("Item",self.item, force=True)
|
||||
except Exception:
|
||||
frappe.throw("""Not permitted. Please disable the Test Template""")
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ frappe.ui.form.on('Patient Appointment', {
|
||||
frm.set_value('appointment_time', selected_slot);
|
||||
frm.set_value('duration', data.time_per_appointment);
|
||||
d.hide();
|
||||
frm.enable_save();
|
||||
frm.save();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -292,10 +292,10 @@ def get_events(start, end, filters=None):
|
||||
conditions = get_event_conditions("Patient Appointment", filters)
|
||||
data = frappe.db.sql("""select name, patient, physician, status,
|
||||
duration, timestamp(appointment_date, appointment_time) as
|
||||
'start' from `tabPatient Appointment` where
|
||||
'appointment_date' 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.end = item.start + datetime.timedelta(minutes = item.duration)
|
||||
item.appointment_datetime = item.appointment_date + datetime.timedelta(minutes = item.duration)
|
||||
return data
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
margin-bottom: -4px;
|
||||
}
|
||||
|
||||
.medical_record-row > * {
|
||||
z-index: -999;
|
||||
}
|
||||
|
||||
.date-indicator {
|
||||
background:none;
|
||||
font-size:12px;
|
||||
|
||||
@@ -15,6 +15,8 @@ develop_version = '10.x.x-develop'
|
||||
|
||||
error_report_email = "support@erpnext.com"
|
||||
|
||||
docs_app = "foundation"
|
||||
|
||||
app_include_js = "assets/js/erpnext.min.js"
|
||||
app_include_css = "assets/css/erpnext.css"
|
||||
web_include_js = "assets/js/erpnext-web.min.js"
|
||||
|
||||
@@ -45,14 +45,21 @@ class Employee(NestedSet):
|
||||
self.validate_prefered_email()
|
||||
|
||||
if self.user_id:
|
||||
self.validate_for_enabled_user_id()
|
||||
self.validate_duplicate_user_id()
|
||||
self.validate_user_details()
|
||||
else:
|
||||
existing_user_id = frappe.db.get_value("Employee", self.name, "user_id")
|
||||
if existing_user_id:
|
||||
frappe.permissions.remove_user_permission(
|
||||
"Employee", self.name, existing_user_id)
|
||||
|
||||
def validate_user_details(self):
|
||||
data = frappe.db.get_value('User',
|
||||
self.user_id, ['enabled', 'user_image'], as_dict=1)
|
||||
|
||||
self.image = data.get("user_image")
|
||||
self.validate_for_enabled_user_id(data.get("enabled", 0))
|
||||
self.validate_duplicate_user_id()
|
||||
|
||||
def update_nsm_model(self):
|
||||
frappe.utils.nestedset.update_nsm(self)
|
||||
|
||||
@@ -133,10 +140,10 @@ class Employee(NestedSet):
|
||||
if self.status == 'Left' and not self.relieving_date:
|
||||
throw(_("Please enter relieving date."))
|
||||
|
||||
def validate_for_enabled_user_id(self):
|
||||
def validate_for_enabled_user_id(self, enabled):
|
||||
if not self.status == 'Active':
|
||||
return
|
||||
enabled = frappe.db.get_value("User", self.user_id, "enabled")
|
||||
|
||||
if enabled is None:
|
||||
frappe.throw(_("User {0} does not exist").format(self.user_id))
|
||||
if enabled == 0:
|
||||
|
||||
@@ -58,7 +58,7 @@ class EmployeeAdvance(Document):
|
||||
select sum(ifnull(allocated_amount, 0))
|
||||
from `tabExpense Claim Advance`
|
||||
where employee_advance = %s and docstatus=1 and allocated_amount > 0
|
||||
""", self.name)[0][0]
|
||||
""", self.name)[0][0] or 0
|
||||
|
||||
frappe.db.set_value("Employee Advance", self.name, "claimed_amount", claimed_amount)
|
||||
|
||||
|
||||
@@ -71,19 +71,22 @@ frappe.ui.form.on('Employee Loan', {
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
mode_of_payment: function (frm) {
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_bank_cash_account",
|
||||
args: {
|
||||
"mode_of_payment": frm.doc.mode_of_payment,
|
||||
"company": frm.doc.company
|
||||
},
|
||||
callback: function (r, rt) {
|
||||
if (r.message) {
|
||||
frm.set_value("payment_account", r.message.account);
|
||||
if (frm.doc.mode_of_payment && frm.doc.company) {
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_bank_cash_account",
|
||||
args: {
|
||||
"mode_of_payment": frm.doc.mode_of_payment,
|
||||
"company": frm.doc.company
|
||||
},
|
||||
callback: function (r, rt) {
|
||||
if (r.message) {
|
||||
frm.set_value("payment_account", r.message.account);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
employee_loan_application: function (frm) {
|
||||
|
||||
@@ -29,8 +29,13 @@ class EmployeeLoanApplication(Document):
|
||||
if self.repayment_method == "Repay Fixed Amount per Period":
|
||||
monthly_interest_rate = flt(self.rate_of_interest) / (12 *100)
|
||||
if monthly_interest_rate:
|
||||
monthly_interest_amount = self.loan_amount * monthly_interest_rate
|
||||
if monthly_interest_amount >= self.repayment_amount:
|
||||
frappe.throw(_("Repayment amount {} should be greater than monthly interest amount {}").
|
||||
format(self.repayment_amount, monthly_interest_amount))
|
||||
|
||||
self.repayment_periods = math.ceil((math.log(self.repayment_amount) -
|
||||
math.log(self.repayment_amount - (self.loan_amount*monthly_interest_rate))) /
|
||||
math.log(self.repayment_amount - (monthly_interest_amount))) /
|
||||
(math.log(1 + monthly_interest_rate)))
|
||||
else:
|
||||
self.repayment_periods = self.loan_amount / self.repayment_amount
|
||||
|
||||
@@ -30,7 +30,7 @@ class ExpenseClaim(AccountsController):
|
||||
self.validate_expense_approver()
|
||||
self.calculate_total_amount()
|
||||
set_employee_name(self)
|
||||
self.set_expense_account()
|
||||
self.set_expense_account(validate=True)
|
||||
self.set_payable_account()
|
||||
self.set_cost_center()
|
||||
self.set_status()
|
||||
@@ -224,10 +224,11 @@ class ExpenseClaim(AccountsController):
|
||||
self.total_advance_amount += flt(d.allocated_amount)
|
||||
|
||||
if self.total_advance_amount:
|
||||
if flt(self.total_advance_amount) > flt(self.total_claimed_amount):
|
||||
precision = self.precision("total_advance_amount")
|
||||
if flt(self.total_advance_amount, precision) > flt(self.total_claimed_amount, precision):
|
||||
frappe.throw(_("Total advance amount cannot be greater than total claimed amount"))
|
||||
if self.total_sanctioned_amount \
|
||||
and flt(self.total_advance_amount) > flt(self.total_sanctioned_amount):
|
||||
and flt(self.total_advance_amount, precision) > flt(self.total_sanctioned_amount, precision):
|
||||
frappe.throw(_("Total advance amount cannot be greater than total sanctioned amount"))
|
||||
|
||||
def validate_sanctioned_amount(self):
|
||||
@@ -235,9 +236,9 @@ class ExpenseClaim(AccountsController):
|
||||
if flt(d.sanctioned_amount) > flt(d.claim_amount):
|
||||
frappe.throw(_("Sanctioned Amount cannot be greater than Claim Amount in Row {0}.").format(d.idx))
|
||||
|
||||
def set_expense_account(self):
|
||||
def set_expense_account(self, validate=False):
|
||||
for expense in self.expenses:
|
||||
if not expense.default_account:
|
||||
if not expense.default_account or not validate:
|
||||
expense.default_account = get_expense_claim_account(expense.expense_type, self.company)["account"]
|
||||
|
||||
def update_reimbursed_amount(doc):
|
||||
|
||||
@@ -113,20 +113,17 @@ frappe.ui.form.on('Salary Slip Timesheet', {
|
||||
// Get leave details
|
||||
//---------------------------------------------------------------------
|
||||
var get_emp_and_leave_details = function(doc, dt, dn) {
|
||||
if(!doc.start_date){
|
||||
return frappe.call({
|
||||
method: 'get_emp_and_leave_details',
|
||||
doc: locals[dt][dn],
|
||||
callback: function(r, rt) {
|
||||
cur_frm.refresh();
|
||||
calculate_all(doc, dt, dn);
|
||||
}
|
||||
});
|
||||
}
|
||||
return frappe.call({
|
||||
method: 'get_emp_and_leave_details',
|
||||
doc: locals[dt][dn],
|
||||
callback: function(r, rt) {
|
||||
cur_frm.refresh();
|
||||
calculate_all(doc, dt, dn);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cur_frm.cscript.employee = function(doc,dt,dn){
|
||||
doc.salary_structure = ''
|
||||
get_emp_and_leave_details(doc, dt, dn);
|
||||
}
|
||||
|
||||
@@ -249,4 +246,4 @@ var total_work_hours = function(frm, dt, dn) {
|
||||
frm.refresh_field('gross_pay');
|
||||
calculate_net_pay(frm.doc, dt, dn);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +181,8 @@ class SalarySlip(TransactionBase):
|
||||
if len(st_name) > 1:
|
||||
frappe.msgprint(_("Multiple active Salary Structures found for employee {0} for the given dates")
|
||||
.format(self.employee), title=_('Warning'))
|
||||
return st_name and st_name[0][0] or ''
|
||||
self.salary_structure = st_name and st_name[0][0] or ''
|
||||
return self.salary_structure
|
||||
else:
|
||||
self.salary_structure = None
|
||||
frappe.msgprint(_("No active or default Salary Structure found for employee {0} for the given dates")
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cstr, add_days, date_diff
|
||||
from frappe.utils import cstr, add_days, date_diff, getdate
|
||||
from frappe import _
|
||||
from frappe.utils.csvutils import UnicodeWriter
|
||||
from frappe.model.document import Document
|
||||
@@ -48,8 +48,9 @@ def add_data(w, args):
|
||||
for employee in employees:
|
||||
existing_attendance = {}
|
||||
if existing_attendance_records \
|
||||
and tuple([date, employee.name]) in existing_attendance_records:
|
||||
existing_attendance = existing_attendance_records[tuple([date, employee.name])]
|
||||
and tuple([getdate(date), employee.name]) in existing_attendance_records:
|
||||
existing_attendance = existing_attendance_records[tuple([getdate(date), employee.name])]
|
||||
|
||||
row = [
|
||||
existing_attendance and existing_attendance.name or "",
|
||||
employee.name, employee.employee_name, date,
|
||||
@@ -114,6 +115,7 @@ def upload():
|
||||
if not row: continue
|
||||
row_idx = i + 5
|
||||
d = frappe._dict(zip(columns, row))
|
||||
|
||||
d["doctype"] = "Attendance"
|
||||
if d.name:
|
||||
d["docstatus"] = frappe.db.get_value("Attendance", d.name, "docstatus")
|
||||
@@ -121,6 +123,8 @@ def upload():
|
||||
try:
|
||||
check_record(d)
|
||||
ret.append(import_doc(d, "Attendance", 1, row_idx, submit=True))
|
||||
except AttributeError:
|
||||
pass
|
||||
except Exception as e:
|
||||
error = True
|
||||
ret.append('Error for row (#%d) %s : %s' % (row_idx,
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, requests, json
|
||||
from frappe.utils import now, nowdate, cint
|
||||
from frappe.utils.nestedset import get_root_of
|
||||
from frappe.contacts.doctype.contact.contact import get_default_contact
|
||||
|
||||
@frappe.whitelist()
|
||||
def enable_hub():
|
||||
hub_settings = frappe.get_doc('Hub Settings')
|
||||
hub_settings.register()
|
||||
frappe.db.commit()
|
||||
return hub_settings
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_items(start=0, limit=20, category=None, order_by=None, company=None, text=None):
|
||||
connection = get_client_connection()
|
||||
filters = {
|
||||
'hub_category': category,
|
||||
}
|
||||
if text:
|
||||
filters.update({'item_name': ('like', '%' + text + '%')})
|
||||
if company:
|
||||
filters.update({'company_name': company})
|
||||
|
||||
response = connection.get_list('Hub Item',
|
||||
limit_start=start, limit_page_length=limit,
|
||||
filters=filters)
|
||||
return response
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_categories():
|
||||
connection = get_client_connection()
|
||||
response = connection.get_list('Hub Category')
|
||||
return response
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_details(hub_sync_id=None):
|
||||
if not hub_sync_id:
|
||||
return
|
||||
connection = get_client_connection()
|
||||
return connection.get_doc('Hub Item', hub_sync_id)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_company_details(hub_sync_id):
|
||||
connection = get_client_connection()
|
||||
return connection.get_doc('Hub Company', hub_sync_id)
|
||||
|
||||
def get_client_connection():
|
||||
# frappeclient connection
|
||||
hub_connection = get_hub_connection()
|
||||
return hub_connection.connection
|
||||
|
||||
def get_hub_connection():
|
||||
hub_connector = frappe.get_doc(
|
||||
'Data Migration Connector', 'Hub Connector')
|
||||
hub_connection = hub_connector.get_connection()
|
||||
return hub_connection
|
||||
|
||||
def make_opportunity(buyer_name, email_id):
|
||||
buyer_name = "HUB-" + buyer_name
|
||||
|
||||
if not frappe.db.exists('Lead', {'email_id': email_id}):
|
||||
lead = frappe.new_doc("Lead")
|
||||
lead.lead_name = buyer_name
|
||||
lead.email_id = email_id
|
||||
lead.save(ignore_permissions=True)
|
||||
|
||||
o = frappe.new_doc("Opportunity")
|
||||
o.enquiry_from = "Lead"
|
||||
o.lead = frappe.get_all("Lead", filters={"email_id": email_id}, fields = ["name"])[0]["name"]
|
||||
o.save(ignore_permissions=True)
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_rfq_and_send_opportunity(item, supplier):
|
||||
supplier = make_supplier(supplier)
|
||||
contact = make_contact(supplier)
|
||||
item = make_item(item)
|
||||
rfq = make_rfq(item, supplier, contact)
|
||||
status = send_opportunity(contact)
|
||||
|
||||
return {
|
||||
'rfq': rfq,
|
||||
'hub_document_created': status
|
||||
}
|
||||
|
||||
def make_supplier(supplier):
|
||||
# make supplier if not already exists
|
||||
supplier = frappe._dict(json.loads(supplier))
|
||||
|
||||
if not frappe.db.exists('Supplier', {'supplier_name': supplier.supplier_name}):
|
||||
supplier_doc = frappe.get_doc({
|
||||
'doctype': 'Supplier',
|
||||
'supplier_name': supplier.supplier_name,
|
||||
'supplier_type': supplier.supplier_type,
|
||||
'supplier_email': supplier.supplier_email
|
||||
}).insert()
|
||||
else:
|
||||
supplier_doc = frappe.get_doc('Supplier', supplier.supplier_name)
|
||||
|
||||
return supplier_doc
|
||||
|
||||
def make_contact(supplier):
|
||||
contact_name = get_default_contact('Supplier', supplier.supplier_name)
|
||||
# make contact if not already exists
|
||||
if not contact_name:
|
||||
contact = frappe.get_doc({
|
||||
'doctype': 'Contact',
|
||||
'first_name': supplier.supplier_name,
|
||||
'email_id': supplier.supplier_email,
|
||||
'is_primary_contact': 1,
|
||||
'links': [
|
||||
{'link_doctype': 'Supplier', 'link_name': supplier.supplier_name}
|
||||
]
|
||||
}).insert()
|
||||
else:
|
||||
contact = frappe.get_doc('Contact', contact_name)
|
||||
|
||||
return contact
|
||||
|
||||
def make_item(item):
|
||||
# make item if not already exists
|
||||
item = frappe._dict(json.loads(item))
|
||||
|
||||
if not frappe.db.exists('Item', {'item_code': item.item_code}):
|
||||
item_doc = frappe.get_doc({
|
||||
'doctype': 'Item',
|
||||
'item_code': item.item_code,
|
||||
'item_group': item.item_group,
|
||||
'is_item_from_hub': 1
|
||||
}).insert()
|
||||
else:
|
||||
item_doc = frappe.get_doc('Item', item.item_code)
|
||||
|
||||
return item_doc
|
||||
|
||||
def make_rfq(item, supplier, contact):
|
||||
# make rfq
|
||||
rfq = frappe.get_doc({
|
||||
'doctype': 'Request for Quotation',
|
||||
'transaction_date': nowdate(),
|
||||
'status': 'Draft',
|
||||
'company': frappe.db.get_single_value('Hub Settings', 'company'),
|
||||
'message_for_supplier': 'Please supply the specified items at the best possible rates',
|
||||
'suppliers': [
|
||||
{ 'supplier': supplier.name, 'contact': contact.name }
|
||||
],
|
||||
'items': [
|
||||
{
|
||||
'item_code': item.item_code,
|
||||
'qty': 1,
|
||||
'schedule_date': nowdate(),
|
||||
'warehouse': item.default_warehouse or get_root_of("Warehouse"),
|
||||
'description': item.description,
|
||||
'uom': item.stock_uom
|
||||
}
|
||||
]
|
||||
}).insert()
|
||||
|
||||
rfq.save()
|
||||
rfq.submit()
|
||||
return rfq
|
||||
|
||||
def send_opportunity(contact):
|
||||
# Make Hub Message on Hub with lead data
|
||||
doc = {
|
||||
'doctype': 'Lead',
|
||||
'lead_name': frappe.db.get_single_value('Hub Settings', 'company'),
|
||||
'email_id': frappe.db.get_single_value('Hub Settings', 'user')
|
||||
}
|
||||
|
||||
args = frappe._dict(dict(
|
||||
doctype='Hub Message',
|
||||
reference_doctype='Lead',
|
||||
data=json.dumps(doc),
|
||||
user=contact.email_id
|
||||
))
|
||||
|
||||
connection = get_hub_connection()
|
||||
response = connection.insert('Hub Message', args)
|
||||
|
||||
return response.ok
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"condition": "{'name': ('=', frappe.db.get_single_value('Hub Settings', 'company'))}",
|
||||
"creation": "2017-09-07 11:38:43.169065",
|
||||
"docstatus": 0,
|
||||
"doctype": "Data Migration Mapping",
|
||||
"fields": [
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "name",
|
||||
"remote_fieldname": "company_name"
|
||||
},
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "country",
|
||||
"remote_fieldname": "country"
|
||||
},
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "\"city\"",
|
||||
"remote_fieldname": "seller_city"
|
||||
},
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "eval:frappe.local.site",
|
||||
"remote_fieldname": "site_name"
|
||||
},
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "eval:frappe.session.user",
|
||||
"remote_fieldname": "user"
|
||||
}
|
||||
],
|
||||
"idx": 2,
|
||||
"local_doctype": "Company",
|
||||
"mapping_name": "Company to Hub Company",
|
||||
"mapping_type": "Push",
|
||||
"migration_id_field": "hub_sync_id",
|
||||
"modified": "2017-10-09 17:30:17.853929",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Company to Hub Company",
|
||||
"owner": "Administrator",
|
||||
"page_length": 10,
|
||||
"remote_objectname": "Hub Company",
|
||||
"remote_primary_key": "name"
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import frappe, json
|
||||
|
||||
def pre_process(doc):
|
||||
return json.loads(doc['data'])
|
||||
|
||||
def post_process(remote_doc=None, local_doc=None, **kwargs):
|
||||
if not local_doc:
|
||||
return
|
||||
|
||||
hub_message = remote_doc
|
||||
# update hub message on hub
|
||||
hub_connector = frappe.get_doc('Data Migration Connector', 'Hub Connector')
|
||||
connection = hub_connector.get_connection()
|
||||
connection.update('Hub Message', dict(
|
||||
status='Synced'
|
||||
), hub_message['name'])
|
||||
|
||||
# make opportunity after lead is created
|
||||
lead = local_doc
|
||||
opportunity = frappe.get_doc({
|
||||
'doctype': 'Opportunity',
|
||||
'naming_series': 'OPTY-',
|
||||
'opportunity_type': 'Hub',
|
||||
'enquiry_from': 'Lead',
|
||||
'status': 'Open',
|
||||
'lead': lead.name,
|
||||
'company': lead.company,
|
||||
'transaction_date': frappe.utils.today()
|
||||
}).insert()
|
||||
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"condition": "{'reference_doctype': 'Lead', 'user': frappe.db.get_single_value('Hub Settings', 'user'), 'status': 'Pending'}",
|
||||
"creation": "2017-09-20 15:06:40.279930",
|
||||
"docstatus": 0,
|
||||
"doctype": "Data Migration Mapping",
|
||||
"fields": [
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "email_id",
|
||||
"remote_fieldname": "email_id"
|
||||
},
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "lead_name",
|
||||
"remote_fieldname": "lead_name"
|
||||
}
|
||||
],
|
||||
"idx": 0,
|
||||
"local_doctype": "Lead",
|
||||
"local_primary_key": "email_id",
|
||||
"mapping_name": "Hub Message to Lead",
|
||||
"mapping_type": "Pull",
|
||||
"migration_id_field": "hub_sync_id",
|
||||
"modified": "2017-10-09 17:30:17.908830",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Hub Message to Lead",
|
||||
"owner": "frappetest@gmail.com",
|
||||
"page_length": 10,
|
||||
"remote_objectname": "Hub Message",
|
||||
"remote_primary_key": "name"
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
{
|
||||
"condition": "{\"publish_in_hub\": 1}",
|
||||
"creation": "2017-09-07 13:27:52.726350",
|
||||
"docstatus": 0,
|
||||
"doctype": "Data Migration Mapping",
|
||||
"fields": [
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "item_code",
|
||||
"remote_fieldname": "item_code"
|
||||
},
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "item_name",
|
||||
"remote_fieldname": "item_name"
|
||||
},
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "eval:frappe.db.get_default(\"company\")",
|
||||
"remote_fieldname": "company_name"
|
||||
},
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "image",
|
||||
"remote_fieldname": "image"
|
||||
},
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "item_group",
|
||||
"remote_fieldname": "item_group"
|
||||
},
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "eval:frappe.session.user",
|
||||
"remote_fieldname": "seller"
|
||||
},
|
||||
{
|
||||
"is_child_table": 0,
|
||||
"local_fieldname": "eval:frappe.db.get_default(\"country\")",
|
||||
"remote_fieldname": "country"
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"local_doctype": "Item",
|
||||
"mapping_name": "Item to Hub Item",
|
||||
"mapping_type": "Push",
|
||||
"migration_id_field": "hub_sync_id",
|
||||
"modified": "2017-10-09 17:30:17.890337",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Item to Hub Item",
|
||||
"owner": "Administrator",
|
||||
"page_length": 10,
|
||||
"remote_objectname": "Hub Item",
|
||||
"remote_primary_key": "item_code"
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"creation": "2017-09-07 11:39:38.445902",
|
||||
"docstatus": 0,
|
||||
"doctype": "Data Migration Plan",
|
||||
"idx": 1,
|
||||
"mappings": [
|
||||
{
|
||||
"enabled": 1,
|
||||
"mapping": "Company to Hub Company"
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"mapping": "Item to Hub Item"
|
||||
},
|
||||
{
|
||||
"enabled": 1,
|
||||
"mapping": "Hub Message to Lead"
|
||||
}
|
||||
],
|
||||
"modified": "2017-10-09 17:30:17.680059",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Hub Node",
|
||||
"name": "Hub Sync",
|
||||
"owner": "Administrator",
|
||||
"plan_name": "Hub Sync"
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Hub Category', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
||||
@@ -1,275 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:hub_category_name",
|
||||
"beta": 0,
|
||||
"creation": "2017-08-22 11:31:10.410322",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "hub_category_name",
|
||||
"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": "Category 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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "parent_hub_category",
|
||||
"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": "Parent Category",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Hub Category",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "is_group",
|
||||
"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 Group",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "lft",
|
||||
"fieldtype": "Int",
|
||||
"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": "Left",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rgt",
|
||||
"fieldtype": "Int",
|
||||
"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": "Right",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "old_parent",
|
||||
"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": "Old Parent",
|
||||
"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,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-09-03 22:04:22.958831",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Hub Node",
|
||||
"name": "Hub Category",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "hub_category_name",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
from frappe.model.document import Document
|
||||
|
||||
class HubCategory(NestedSet):
|
||||
pass
|
||||
@@ -1,4 +0,0 @@
|
||||
frappe.treeview_settings["Hub Category"] = {
|
||||
title: __("Hub Category"),
|
||||
breadcrumb: "Hub"
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Hub Category", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Hub Category
|
||||
() => frappe.tests.make('Hub Category', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestHubCategory(unittest.TestCase):
|
||||
pass
|
||||
@@ -1,87 +0,0 @@
|
||||
frappe.ui.form.on("Hub Settings", {
|
||||
refresh: function(frm) {
|
||||
frm.add_custom_button(__('Logs'),
|
||||
() => frappe.set_route('List', 'Data Migration Run', {
|
||||
data_migration_plan: 'Hub Sync'
|
||||
}));
|
||||
|
||||
frm.trigger("enabled");
|
||||
if (frm.doc.enabled) {
|
||||
frm.add_custom_button(__('View Hub'),
|
||||
() => frappe.set_route('hub'));
|
||||
frm.add_custom_button(__('Sync'),
|
||||
() => frm.call('sync'));
|
||||
}
|
||||
},
|
||||
onload: function(frm) {
|
||||
if(!frm.doc.country) {
|
||||
frm.set_value("country", frappe.defaults.get_default("Country"));
|
||||
}
|
||||
if(!frm.doc.company) {
|
||||
frm.set_value("company", frappe.defaults.get_default("Company"));
|
||||
}
|
||||
},
|
||||
onload_post_render: function(frm) {
|
||||
if(frm.get_field("unregister_from_hub").$input)
|
||||
frm.get_field("unregister_from_hub").$input.addClass("btn-danger");
|
||||
},
|
||||
on_update: function(frm) {
|
||||
},
|
||||
enabled: function(frm) {
|
||||
if(!frm.doc.enabled) {
|
||||
frm.trigger("set_enable_hub_primary_button");
|
||||
} else {
|
||||
frm.page.set_primary_action(__("Save Settings"), () => {
|
||||
frm.save();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
hub_user_email: function(frm) {
|
||||
if(frm.doc.hub_user_email){
|
||||
frm.set_value("hub_user_name", frappe.user.full_name(frm.doc.hub_user_email));
|
||||
}
|
||||
},
|
||||
|
||||
set_enable_hub_primary_button: (frm) => {
|
||||
frm.page.set_primary_action(__("Enable Hub"), () => {
|
||||
if(frappe.session.user === "Administrator") {
|
||||
frappe.msgprint("Please login as another user.")
|
||||
} else {
|
||||
frappe.verify_password(() => {
|
||||
this.frm.call({
|
||||
doc: this.frm.doc,
|
||||
method: "register",
|
||||
args: {},
|
||||
freeze: true,
|
||||
callback: function(r) {},
|
||||
onerror: function() {
|
||||
frappe.msgprint(__("Wrong Password"));
|
||||
frm.set_value("enabled", 0);
|
||||
}
|
||||
});
|
||||
} );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// update_hub: (frm) => {
|
||||
// this.frm.call({
|
||||
// doc: this.frm.doc,
|
||||
// method: "update_hub",
|
||||
// args: {},
|
||||
// freeze: true,
|
||||
// callback: function(r) { },
|
||||
// onerror: function() { }
|
||||
// });
|
||||
// },
|
||||
|
||||
unregister_from_hub: (frm) => {
|
||||
frappe.verify_password(() => {
|
||||
var d = frappe.confirm(__('Are you sure you want to unregister?'), () => {
|
||||
frm.call('unregister');
|
||||
}, () => {}, __('Confirm Action'));
|
||||
d.get_primary_btn().addClass("btn-danger");
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -1,525 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 1,
|
||||
"creation": "2015-02-18 00:59:34.560476",
|
||||
"custom": 0,
|
||||
"description": "",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "enabled",
|
||||
"fieldtype": "Check",
|
||||
"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": "Enabled",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "suspended",
|
||||
"fieldtype": "Check",
|
||||
"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": "Suspended",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "user",
|
||||
"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": "User",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "User",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:(!doc.enabled)",
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "seller_profile_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company and Seller Profile",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 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": 1,
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "country",
|
||||
"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": "Country",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Country",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "seller_description",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "enabled",
|
||||
"fieldname": "publish_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Publish",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "publish",
|
||||
"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": "Publish Items to Hub",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "publish",
|
||||
"fieldname": "publish_pricing",
|
||||
"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": "Publish Pricing",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:(doc.publish && doc.publish_pricing)",
|
||||
"fieldname": "selling_price_list",
|
||||
"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": "Selling Price List",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Price List",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "publish",
|
||||
"fieldname": "publish_availability",
|
||||
"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": "Publish Availability",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "publish",
|
||||
"fieldname": "last_sync_datetime",
|
||||
"fieldtype": "Datetime",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Last Sync On",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"collapsible_depends_on": "",
|
||||
"columns": 0,
|
||||
"depends_on": "enabled",
|
||||
"fieldname": "unregister_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Unregister",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "unregister_from_hub",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Unregister from Hub",
|
||||
"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,
|
||||
"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": "2017-09-21 12:13:50.841646",
|
||||
"modified_by": "manas@erpnext.com",
|
||||
"module": "Hub Node",
|
||||
"name": "Hub Settings",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, requests, json
|
||||
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import add_years, now, get_datetime, get_datetime_str
|
||||
from frappe import _
|
||||
from erpnext.utilities.product import get_price, get_qty_in_stock
|
||||
from six import string_types
|
||||
|
||||
hub_url = "https://hubmarket.org"
|
||||
|
||||
class HubSetupError(frappe.ValidationError): pass
|
||||
|
||||
class HubSettings(Document):
|
||||
|
||||
def validate(self):
|
||||
if self.publish_pricing and not self.selling_price_list:
|
||||
frappe.throw(_("Please select a Price List to publish pricing"))
|
||||
|
||||
def get_hub_url(self):
|
||||
return hub_url
|
||||
|
||||
def sync(self):
|
||||
"""Create and execute Data Migration Run for Hub Sync plan"""
|
||||
frappe.has_permission('Hub Settings', throw=True)
|
||||
|
||||
doc = frappe.get_doc({
|
||||
'doctype': 'Data Migration Run',
|
||||
'data_migration_plan': 'Hub Sync',
|
||||
'data_migration_connector': 'Hub Connector'
|
||||
}).insert()
|
||||
|
||||
doc.run()
|
||||
|
||||
def register(self):
|
||||
""" Create a User on hub.erpnext.org and return username/password """
|
||||
data = {
|
||||
'email': frappe.session.user
|
||||
}
|
||||
post_url = hub_url + '/api/method/hub.hub.api.register'
|
||||
|
||||
response = requests.post(post_url, data=data)
|
||||
response.raise_for_status()
|
||||
message = response.json().get('message')
|
||||
|
||||
if message and message.get('password'):
|
||||
self.user = frappe.session.user
|
||||
self.create_hub_connector(message)
|
||||
self.company = frappe.defaults.get_user_default('company')
|
||||
self.enabled = 1
|
||||
self.save()
|
||||
|
||||
def unregister(self):
|
||||
""" Disable the User on hub.erpnext.org"""
|
||||
|
||||
hub_connector = frappe.get_doc(
|
||||
'Data Migration Connector', 'Hub Connector')
|
||||
|
||||
connection = hub_connector.get_connection()
|
||||
response_doc = connection.update('User', frappe._dict({'enabled': 0}), hub_connector.username)
|
||||
|
||||
if response_doc['enabled'] == 0:
|
||||
self.enabled = 0
|
||||
self.save()
|
||||
|
||||
def create_hub_connector(self, message):
|
||||
if frappe.db.exists('Data Migration Connector', 'Hub Connector'):
|
||||
hub_connector = frappe.get_doc('Data Migration Connector', 'Hub Connector')
|
||||
hub_connector.username = message['email']
|
||||
hub_connector.password = message['password']
|
||||
hub_connector.save()
|
||||
return
|
||||
|
||||
frappe.get_doc({
|
||||
'doctype': 'Data Migration Connector',
|
||||
'connector_type': 'Frappe',
|
||||
'connector_name': 'Hub Connector',
|
||||
'hostname': hub_url,
|
||||
'username': message['email'],
|
||||
'password': message['password']
|
||||
}).insert()
|
||||
|
||||
def reset_hub_publishing_settings(last_sync_datetime = ""):
|
||||
doc = frappe.get_doc("Hub Settings", "Hub Settings")
|
||||
doc.reset_publishing_settings(last_sync_datetime)
|
||||
doc.in_callback = 1
|
||||
doc.save()
|
||||
|
||||
def reset_hub_settings(last_sync_datetime = ""):
|
||||
doc = frappe.get_doc("Hub Settings", "Hub Settings")
|
||||
doc.reset_publishing_settings(last_sync_datetime)
|
||||
doc.reset_enable()
|
||||
doc.in_callback = 1
|
||||
doc.save()
|
||||
frappe.msgprint(_("Successfully unregistered."))
|
||||
|
||||
@frappe.whitelist()
|
||||
def sync():
|
||||
hub_settings = frappe.get_doc('Hub Settings')
|
||||
hub_settings.sync()
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Hub Settings", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially('Hub Settings', [
|
||||
// insert a new Hub Settings
|
||||
() => frappe.tests.make([
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestHubSettings(unittest.TestCase):
|
||||
pass
|
||||
@@ -1,873 +0,0 @@
|
||||
/* globals Hub, HubList */
|
||||
|
||||
frappe.provide('erpnext.hub');
|
||||
|
||||
frappe.pages['hub'].on_page_load = function(wrapper) {
|
||||
const page = frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: 'Hub',
|
||||
single_col: false
|
||||
});
|
||||
|
||||
wrapper.hub_page = new erpnext.hub.Hub({ page });
|
||||
};
|
||||
|
||||
frappe.pages['hub'].on_page_show = function(wrapper) {
|
||||
const hub_page = wrapper.hub_page;
|
||||
const [hub, type, id] = frappe.get_route();
|
||||
|
||||
if (!(hub || type || id)) {
|
||||
hub_page.go_to_home_page();
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === "Products") {
|
||||
hub_page.go_to_item_page(id);
|
||||
} else if (type === "Company") {
|
||||
hub_page.go_to_company_page(id);
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.hub.Hub = class Hub {
|
||||
constructor({ page }) {
|
||||
this.page = page;
|
||||
frappe.require('/assets/erpnext/css/hub.css', () => {
|
||||
this.setup();
|
||||
});
|
||||
}
|
||||
|
||||
setup() {
|
||||
this.setup_header();
|
||||
this.company_cache = {};
|
||||
this.item_cache = {};
|
||||
this.filters = {};
|
||||
this.order_by = '';
|
||||
|
||||
this.$hub_main_section =
|
||||
$(`<div class='hub-main-section'>`).appendTo(this.page.body);
|
||||
this.bind_events();
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.$hub_main_section.empty();
|
||||
this.page.page_form.hide();
|
||||
|
||||
const $layout_main = this.page.wrapper.find('.layout-main');
|
||||
const $page_head = this.page.wrapper.find('.page-head');
|
||||
|
||||
frappe.model.with_doc('Hub Settings', 'Hub Settings', () => {
|
||||
this.hub_settings = frappe.get_doc('Hub Settings');
|
||||
|
||||
if(this.hub_settings.enabled == 0) {
|
||||
let $empty_state = this.page.get_empty_state(
|
||||
__("Register for Hub"),
|
||||
__(`Let other ERPNext users discover your products
|
||||
and automate workflow with Supplier from within ERPNext.`),
|
||||
__("Register")
|
||||
);
|
||||
|
||||
$page_head.hide();
|
||||
$layout_main
|
||||
.find('.layout-side-section, .layout-main-section-wrapper')
|
||||
.hide();
|
||||
$layout_main.append($empty_state);
|
||||
|
||||
$empty_state.find('.btn-primary').on('click', () => {
|
||||
this.register_for_hub();
|
||||
});
|
||||
} else {
|
||||
$page_head.show();
|
||||
$layout_main.find('.page-card-container').remove();
|
||||
$layout_main.find('.layout-side-section, .layout-main-section-wrapper').show();
|
||||
this.setup_live_state();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
register_for_hub() {
|
||||
if (frappe.session.user.includes('Administrator')) {
|
||||
frappe.throw(__('Please login as another user.'))
|
||||
}
|
||||
frappe.verify_password(() => {
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.enable_hub',
|
||||
callback: (r) => {
|
||||
if(r.message.enabled == 1) {
|
||||
Object.assign(this.hub_settings, r.message);
|
||||
this.refresh();
|
||||
this.prompt_for_item_sync();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
prompt_for_item_sync() {
|
||||
frappe.call({
|
||||
method: 'frappe.client.get_list',
|
||||
args: {
|
||||
doctype: 'Data Migration Run',
|
||||
filters: {
|
||||
'data_migration_plan': 'Hub Sync'
|
||||
},
|
||||
limit_page_length: 1
|
||||
},
|
||||
callback: function(r) {
|
||||
if (!r) {
|
||||
frappe.confirm(__('Do you want to publish your Items to Hub ?'), () => {
|
||||
this.sync_items_to_hub();
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setup_header() {
|
||||
this.page.page_title = this.page.wrapper.find('.page-title');
|
||||
this.tag_line = $(`
|
||||
<div class='tag-line-container'>
|
||||
<span class='tag-line text-muted small'>
|
||||
${__('Product listing and discovery for ERPNext users')}
|
||||
</span>
|
||||
</div>`)
|
||||
.appendTo(this.page.page_title);
|
||||
|
||||
this.bind_title();
|
||||
}
|
||||
|
||||
setup_live_state() {
|
||||
if(!this.$search) {
|
||||
this.setup_filters();
|
||||
}
|
||||
this.page.page_form.show();
|
||||
this.setup_menu();
|
||||
this.setup_sidebar();
|
||||
this.render_body();
|
||||
this.setup_lists();
|
||||
}
|
||||
|
||||
setup_filters() {
|
||||
|
||||
// frappe.call({
|
||||
// method: 'erpnext.hub_node.get_categories'
|
||||
// }).then((r) => {
|
||||
// if (r.message) {
|
||||
// const categories = r.message;
|
||||
// console.log("categories", categories);
|
||||
// categories
|
||||
// .map(c => c.hub_category_name)
|
||||
// .map(c => this.sidebar.add_item({
|
||||
// label: c,
|
||||
// on_click: () => {
|
||||
// this.home_item_list &&
|
||||
// this.home_item_list.refresh({
|
||||
// text: '',
|
||||
// start: 0,
|
||||
// limit: 20,
|
||||
// category: c && c !== 'All Categories' ? c : undefined
|
||||
// });
|
||||
// }
|
||||
// }, __('Hub Category')));
|
||||
|
||||
|
||||
// }
|
||||
// });
|
||||
|
||||
// this.category_select = this.page.add_select(__('Category'),
|
||||
// [
|
||||
// {label: __('Sort by Price ...'), value: '' },
|
||||
// {label: __('High to Low'), value: 'price desc' },
|
||||
// {label: __('Low to High'), value: 'price' },
|
||||
// ]
|
||||
// );
|
||||
|
||||
this.price_sort_select = this.page.add_select(__('Sort by Price'),
|
||||
[
|
||||
{label: __('Sort by Price ...'), value: '' },
|
||||
{label: __('High to Low'), value: 'price desc' },
|
||||
{label: __('Low to High'), value: 'price' },
|
||||
]
|
||||
);
|
||||
|
||||
this.criteria_select = this.page.add_select(__('Sort by Criteria'),
|
||||
[
|
||||
{label: __('Most Popular'), value: 'request_count' },
|
||||
{label: __('Newest'), value: 'creation' },
|
||||
]
|
||||
);
|
||||
|
||||
this.price_sort_select.on('change', () => {
|
||||
this.refresh_item_only_page();
|
||||
});
|
||||
|
||||
this.criteria_select.on('change', () => {
|
||||
this.refresh_item_only_page();
|
||||
});
|
||||
|
||||
this.setup_hub_category_filter();
|
||||
this.setup_search();
|
||||
}
|
||||
|
||||
bind_events() {
|
||||
const me = this;
|
||||
this.$hub_main_section
|
||||
.on('click', '.company-link a', function(e) {
|
||||
e.preventDefault();
|
||||
const company_name = $(this).attr('data-company-name');
|
||||
frappe.set_route('hub', 'Company', company_name);
|
||||
})
|
||||
.on('click', '.breadcrumb li', function(e) {
|
||||
e.preventDefault();
|
||||
const $li = $(this);
|
||||
if ($li.attr('data-route') === 'Home') {
|
||||
me.go_to_home_page();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
update_filters() {
|
||||
let price_sort = $(this.price_sort_select).val() || '';
|
||||
let criteria = $(this.criteria_select).val() || '';
|
||||
|
||||
let order_by_params = [];
|
||||
let query_string = '';
|
||||
if(criteria) {
|
||||
order_by_params.push(criteria);
|
||||
// query_string += 'sort_by=' + criteria
|
||||
}
|
||||
if(price_sort) order_by_params.push(price_sort);
|
||||
this.order_by = order_by_params.join(",");
|
||||
// return query_string;
|
||||
}
|
||||
|
||||
reset_filters() {
|
||||
this.order_by = '';
|
||||
$(this.category_select).val('');
|
||||
$(this.price_sort_select).val('');
|
||||
$(this.criteria_select).val('Most Popular');
|
||||
}
|
||||
|
||||
refresh_item_only_page() {
|
||||
this.reset_search();
|
||||
this.update_filters();
|
||||
this.go_to_items_only_page(
|
||||
['hub', 'Products'],
|
||||
'', 'product-list'
|
||||
);
|
||||
}
|
||||
|
||||
bind_title() {
|
||||
this.page.page_title.find('.title-text').on('click', () => {
|
||||
this.go_to_home_page();
|
||||
});
|
||||
}
|
||||
|
||||
render_body() {
|
||||
this.$home_page = $(`
|
||||
<div class = 'hub-home-page'>
|
||||
<div class='banner'></div>
|
||||
<div class='listing-body row'>
|
||||
<div class='main-list-section'></div>
|
||||
</div>
|
||||
</div>
|
||||
`).appendTo(this.$hub_main_section);
|
||||
|
||||
this.$banner = this.$hub_main_section.find('.banner');
|
||||
this.$listing_body = this.$hub_main_section.find('.listing-body');
|
||||
this.$main_list_section = this.$hub_main_section.find('.main-list-section');
|
||||
this.$side_list_section = this.$hub_main_section.find('.side-list-section');
|
||||
}
|
||||
|
||||
setup_lists() {
|
||||
this.home_item_list = new erpnext.hub.HubList({
|
||||
parent: this.$main_list_section,
|
||||
title: 'New',
|
||||
page_length: 20,
|
||||
list_css_class: 'home-product-list',
|
||||
method: 'erpnext.hub_node.get_items',
|
||||
// order_by: 'request_count',
|
||||
filters: {text: '', country: this.country}, // filters at the time of creation
|
||||
on_item_click: (item_code) => {
|
||||
frappe.set_route('hub', 'Products', item_code);
|
||||
}
|
||||
});
|
||||
|
||||
this.home_item_list.setup();
|
||||
}
|
||||
|
||||
setup_hub_category_filter() {
|
||||
const me = this;
|
||||
|
||||
this.hub_category_field = this.page.add_field({
|
||||
fieldtype: 'Autocomplete',
|
||||
label: 'Hub Category',
|
||||
change() {
|
||||
let value = this.get_value();
|
||||
let title = value;
|
||||
if (value === 'All Categories') {
|
||||
// show all items
|
||||
value = null;
|
||||
}
|
||||
|
||||
me.home_item_list.title = title;
|
||||
me.home_item_list.refresh({
|
||||
text: '',
|
||||
start: 0,
|
||||
limit: 20,
|
||||
category: value
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
frappe.call('erpnext.hub_node.get_categories')
|
||||
.then((r) => {
|
||||
if (r.message) {
|
||||
const categories = r.message;
|
||||
|
||||
this.hub_category_field.set_data(
|
||||
categories.map(c => c.hub_category_name)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setup_search() {
|
||||
this.$search = this.page.add_data(__('Search'));
|
||||
this.$search.on('keypress', (e) => {
|
||||
if(e.which === 13) {
|
||||
var search_term = ($(this.$search).val() || '').toLowerCase();
|
||||
this.go_to_items_only_page(
|
||||
['hub', 'search', search_term],
|
||||
'Search results for \'' + search_term + '\'',
|
||||
'search-product-list',
|
||||
{text: search_term}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
go_to_items_only_page(route, title, class_name, filters = {text: ''}, by_item_codes=0) {
|
||||
frappe.set_route(route);
|
||||
this.$hub_main_section.empty();
|
||||
this.filtered_item_list = new erpnext.hub.HubList({
|
||||
parent: this.$hub_main_section,
|
||||
title: title,
|
||||
page_length: 20,
|
||||
list_css_class: class_name,
|
||||
method: 'erpnext.hub_node.get_items',
|
||||
order_by: this.order_by,
|
||||
filters: filters,
|
||||
by_item_codes: by_item_codes
|
||||
});
|
||||
this.filtered_item_list.on_item_click = (item_code) => {
|
||||
frappe.set_route('hub', 'Products', item_code);
|
||||
}
|
||||
this.filtered_item_list.setup();
|
||||
}
|
||||
|
||||
go_to_item_page(item_code) {
|
||||
if(this.item_cache) {
|
||||
let item = this.item_cache[item_code];
|
||||
if(item) {
|
||||
this.render_item_page(item);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
this.item_cache = {};
|
||||
}
|
||||
frappe.call({
|
||||
args:{
|
||||
hub_sync_id: item_code
|
||||
},
|
||||
method: "erpnext.hub_node.get_item_details",
|
||||
callback: (r) => {
|
||||
if (!r || !r.message) return;
|
||||
let item = r.message;
|
||||
this.item_cache[item_code] = item;
|
||||
this.render_item_page(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render_item_page(item) {
|
||||
this.$hub_main_section.empty();
|
||||
|
||||
|
||||
let $item_page =
|
||||
$(this.get_item_page(item))
|
||||
.appendTo(this.$hub_main_section);
|
||||
|
||||
let $company_items = $item_page.find('.company-items');
|
||||
|
||||
let company_item_list = new erpnext.hub.HubList({
|
||||
parent: $company_items,
|
||||
title: 'More by ' + item.company_name,
|
||||
page_length: 5,
|
||||
list_css_class: 'company-item-list',
|
||||
method: 'erpnext.hub_node.get_items',
|
||||
// order_by: 'request_count',
|
||||
filters: {text: '', company_name: item.company_name, country: this.country},
|
||||
paginated: 0,
|
||||
img_size: 150
|
||||
});
|
||||
|
||||
company_item_list.on_item_click = (item_code) => {
|
||||
frappe.set_route('hub', 'Products', item_code);
|
||||
}
|
||||
company_item_list.setup();
|
||||
|
||||
$item_page.find('.rfq-btn')
|
||||
.click((e) => {
|
||||
const $btn = $(e.target);
|
||||
|
||||
this.show_rfq_modal(item)
|
||||
.then(values => {
|
||||
item.item_code = values.item_code;
|
||||
delete values.item_code;
|
||||
|
||||
const supplier = values;
|
||||
return [item, supplier];
|
||||
})
|
||||
.then(([item, supplier]) => {
|
||||
return this.make_rfq(item, supplier, $btn);
|
||||
})
|
||||
.then(r => {
|
||||
console.log(r);
|
||||
if (r.message && r.message.rfq) {
|
||||
$btn.addClass('disabled').html(`<span><i class='fa fa-check'></i> ${__('Quote Requested')}</span>`);
|
||||
} else {
|
||||
throw r;
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e); //eslint-disable-line
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
show_rfq_modal(item) {
|
||||
return new Promise(res => {
|
||||
let fields = [
|
||||
{ label: __('Item Code'), fieldtype: 'Data', fieldname: 'item_code', default: item.item_code },
|
||||
{ fieldtype: 'Column Break' },
|
||||
{ label: __('Item Group'), fieldtype: 'Link', fieldname: 'item_group', default: item.item_group },
|
||||
{ label: __('Supplier Details'), fieldtype: 'Section Break' },
|
||||
{ label: __('Supplier Name'), fieldtype: 'Data', fieldname: 'supplier_name', default: item.company_name },
|
||||
{ label: __('Supplier Email'), fieldtype: 'Data', fieldname: 'supplier_email', default: item.seller },
|
||||
{ fieldtype: 'Column Break' },
|
||||
{ label: __('Supplier Type'), fieldname: 'supplier_type',
|
||||
fieldtype: 'Link', options: 'Supplier Type' }
|
||||
];
|
||||
fields = fields.map(f => { f.reqd = 1; return f; });
|
||||
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __('Request for Quotation'),
|
||||
fields: fields,
|
||||
primary_action_label: __('Send'),
|
||||
primary_action: (values) => {
|
||||
res(values);
|
||||
d.hide();
|
||||
}
|
||||
});
|
||||
|
||||
d.show();
|
||||
});
|
||||
}
|
||||
|
||||
get_company_details(company_id) {
|
||||
this.company_cache = this.company_cache || {};
|
||||
|
||||
return new Promise(resolve => {
|
||||
// get from cache if exists
|
||||
let company_details = this.company_cache[company_id];
|
||||
if(company_details) {
|
||||
resolve(company_details);
|
||||
return;
|
||||
}
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.get_company_details',
|
||||
args: {hub_sync_id: company_id}
|
||||
}).then((r) => {
|
||||
if (r.message) {
|
||||
const company_details = r.message;
|
||||
this.company_cache[company_id] = company_details;
|
||||
resolve(company_details)
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
go_to_company_page(company_id) {
|
||||
this.get_company_details(company_id)
|
||||
.then(this.show_company_page.bind(this));
|
||||
}
|
||||
|
||||
show_company_page(company_details) {
|
||||
this.$hub_main_section.empty();
|
||||
|
||||
let $company_page =
|
||||
$(this.get_company_page(company_details))
|
||||
.appendTo(this.$hub_main_section);
|
||||
|
||||
let $company_items = $company_page.find('.company-items');
|
||||
|
||||
let company_item_list = new erpnext.hub.HubList({
|
||||
parent: $company_items,
|
||||
title: 'More by ' + company_details.company_name,
|
||||
page_length: 5,
|
||||
list_css_class: 'company-item-list',
|
||||
method: 'erpnext.hub_node.get_items',
|
||||
// order_by: 'request_count',
|
||||
filters: {text: '', company: company_details.company_name, country: this.country},
|
||||
paginated: 0,
|
||||
img_size: 150
|
||||
});
|
||||
|
||||
company_item_list.on_item_click = (item_code) => {
|
||||
frappe.set_route('hub', 'Products', item_code);
|
||||
}
|
||||
company_item_list.setup();
|
||||
}
|
||||
|
||||
get_item_page(item) {
|
||||
return `
|
||||
<div class="hub-item-page">
|
||||
<div class="item-header">
|
||||
<div class="item-page-image">
|
||||
${ this.home_item_list.get_item_image(item) }
|
||||
</div>
|
||||
<div class="title-content">
|
||||
<div class="breadcrumbs">
|
||||
${this.get_breadcrumb(item.item_name, "Products") }
|
||||
</div>
|
||||
<div class="title">
|
||||
<h2>${ item.item_name }</h2>
|
||||
</div>
|
||||
<div class="company">
|
||||
<span class="">${ item.company_name }</span>
|
||||
</div>
|
||||
<div class="category">
|
||||
<span class="text-muted">Products</span>
|
||||
</div>
|
||||
<div class="description">
|
||||
<span class="small">${ item.description ? item.description : "" }</span>
|
||||
</div>
|
||||
<div class="price">
|
||||
${ item.formatted_price ? item.formatted_price : '' }
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a class="btn btn-primary rfq-btn">Request A Quote</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="item-more-info"></div>
|
||||
<div class="company-items">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
get_company_page(company_details) {
|
||||
return `
|
||||
<div class="hub-item-page">
|
||||
<div class="item-header">
|
||||
<div class="title-content">
|
||||
<div class="breadcrumbs">
|
||||
${this.get_breadcrumb(company_details.company_name, "Company") }
|
||||
</div>
|
||||
<div class="title">
|
||||
<h2>${ company_details.company_name }</h2>
|
||||
</div>
|
||||
<div class="company">
|
||||
<span class="">${ company_details.country }</span>
|
||||
</div>
|
||||
<div class="description">
|
||||
<span class="small">${ company_details.site_name }</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="item-more-info"></div>
|
||||
<div class="company-items">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
get_breadcrumb(name, type) {
|
||||
return `
|
||||
<ul class="breadcrumb">
|
||||
<li data-route="Home">
|
||||
<a href><span>Home</span></a>
|
||||
</li>
|
||||
<li data-route="List">
|
||||
<a href><span>${type}</span></a>
|
||||
</li>
|
||||
<li class="active">
|
||||
<span>${name}</span>
|
||||
</li>
|
||||
</ul>
|
||||
`;
|
||||
}
|
||||
|
||||
go_to_home_page() {
|
||||
frappe.set_route('hub');
|
||||
this.reset_filters();
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
setup_menu() {
|
||||
if (this.menu_setup) return;
|
||||
|
||||
this.page.add_menu_item(__('Hub Settings'),
|
||||
() => frappe.set_route('Form', 'Hub Settings'));
|
||||
this.page.add_menu_item(__('Refresh'), () => this.refresh());
|
||||
this.page.add_menu_item(__('Sync'), () => this.sync_items_to_hub());
|
||||
|
||||
this.menu_setup = true;
|
||||
}
|
||||
|
||||
sync_items_to_hub() {
|
||||
frappe.call('erpnext.hub_node.doctype.hub_settings.hub_settings.sync')
|
||||
}
|
||||
|
||||
setup_sidebar() {
|
||||
var me = this;
|
||||
this.sidebar = new frappe.ui.Sidebar({
|
||||
wrapper: this.page.wrapper.find('.layout-side-section'),
|
||||
css_class: 'hub-sidebar'
|
||||
});
|
||||
|
||||
this.add_account_to_sidebar();
|
||||
}
|
||||
|
||||
add_account_to_sidebar() {
|
||||
this.sidebar.add_item({
|
||||
label: this.hub_settings.company,
|
||||
on_click: () => frappe.set_route('Form', 'Company', this.hub_settings.company)
|
||||
}, __("Account"));
|
||||
|
||||
this.sidebar.add_item({
|
||||
label: __("My Orders"),
|
||||
on_click: () => frappe.set_route('List', 'Request for Quotation')
|
||||
}, __("Account"));
|
||||
}
|
||||
|
||||
get_search_term() {
|
||||
return this.$search.val();
|
||||
}
|
||||
|
||||
reset_search() {
|
||||
this.$search.val('');
|
||||
}
|
||||
|
||||
make_rfq(item, supplier, btn) {
|
||||
console.log(supplier);
|
||||
return new Promise((resolve, reject) => {
|
||||
frappe.call({
|
||||
method: 'erpnext.hub_node.make_rfq_and_send_opportunity',
|
||||
args: { item, supplier },
|
||||
callback: resolve,
|
||||
btn,
|
||||
}).fail(reject);
|
||||
});
|
||||
}
|
||||
|
||||
go_to_seen_items() {
|
||||
this.go_to_items_only_page(
|
||||
['hub', 'Requested Products'],
|
||||
__('Requested Products'),
|
||||
'requested-product-list',
|
||||
{}, 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.hub.HubList = class HubList {
|
||||
constructor({
|
||||
parent = null,
|
||||
title = 'Products',
|
||||
page_length = 20,
|
||||
list_css_class = '',
|
||||
method = 'erpnext.hub_node.get_items',
|
||||
filters = {text: ''},
|
||||
order_by = '',
|
||||
by_item_codes = 0,
|
||||
paginated = 1,
|
||||
on_item_click = null,
|
||||
img_size = 200
|
||||
}) {
|
||||
this.parent = parent;
|
||||
this.title = title;
|
||||
this.page_length = page_length;
|
||||
this.list_css_class = list_css_class;
|
||||
this.method = method;
|
||||
this.filters = filters;
|
||||
this.order_by = order_by;
|
||||
this.by_item_codes = by_item_codes;
|
||||
this.paginated = paginated;
|
||||
|
||||
this.on_item_click = on_item_click;
|
||||
this.img_size = img_size;
|
||||
}
|
||||
|
||||
// to be called on demand
|
||||
setup() {
|
||||
this.container = $(`
|
||||
<div class='item-list-container ${this.list_css_class}' data-page-length='${this.page_length}'>
|
||||
<div class='item-list-header'>
|
||||
<h3>${this.title}</h3>
|
||||
</div>
|
||||
<div class='item-list'></div>
|
||||
<div class='list-state'>
|
||||
<div class='loading'>
|
||||
<p class='text-muted text-center'>${__('Loading...')}</p>
|
||||
</div>
|
||||
<div class='done hide'>
|
||||
<p class='text-muted text-center'>${__('No more results')}</p>
|
||||
</div>
|
||||
<div class='more text-right'>
|
||||
<button class='btn btn-default btn-sm'>${__('More')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`)
|
||||
.appendTo(this.parent);
|
||||
|
||||
this.$item_list_title = this.container.find('.item-list-header h3');
|
||||
this.$list = this.container.find('.item-list');
|
||||
this.$loading = this.container.find('.loading').hide();
|
||||
this.$more = this.container.find('.more').hide();
|
||||
this.$done = this.container.find('.done');
|
||||
|
||||
this.$more.on('click', () => {
|
||||
this.next_page();
|
||||
});
|
||||
|
||||
this.next_page();
|
||||
}
|
||||
|
||||
refresh(filters = this.filters) {
|
||||
this.reset();
|
||||
this.set_filters(filters);
|
||||
this.next_page();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.$list.empty();
|
||||
}
|
||||
|
||||
set_filters(filters) {
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
next_page() {
|
||||
this.$item_list_title.html(this.title);
|
||||
const start = this.$list.find('.hub-item-wrapper').length;
|
||||
this.$loading.show();
|
||||
|
||||
// build args
|
||||
let args = {
|
||||
start: start,
|
||||
// query one extra
|
||||
limit: this.page_length + 1
|
||||
};
|
||||
Object.assign(args, this.filters);
|
||||
console.log("filters: ", args);
|
||||
args.order_by = this.order_by;
|
||||
args.by_item_codes = this.by_item_codes;
|
||||
|
||||
frappe.call({
|
||||
method: this.method,
|
||||
args: args,
|
||||
callback: (r) => {
|
||||
let items = r.message;
|
||||
console.log("items: ", items);
|
||||
this.render_items(items);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render_items(items) {
|
||||
if(items) {
|
||||
// clear any filler divs
|
||||
this.$list.find('.filler').remove();
|
||||
let done = 0;
|
||||
console.log("items length", items.length);
|
||||
if(items.length && items.length > this.page_length) {
|
||||
// remove the extra queried
|
||||
items.pop();
|
||||
} else {
|
||||
done = 1;
|
||||
}
|
||||
items.forEach((item) => {
|
||||
this.make_item_card(item).appendTo(this.$list);
|
||||
});
|
||||
|
||||
const remainder = items.length % 4;
|
||||
if (remainder > 0) {
|
||||
// fill with filler divs to make flexbox happy
|
||||
Array.from(Array(remainder))
|
||||
.map(r => $('<div class="filler">').css('width', '200px').appendTo(this.$list));
|
||||
}
|
||||
this.update_list_state(done);
|
||||
} else {
|
||||
this.update_list_state(1);
|
||||
}
|
||||
}
|
||||
|
||||
update_list_state(done=0) {
|
||||
this.$loading.hide();
|
||||
if(done) {
|
||||
this.$done.removeClass('hide');
|
||||
this.$more.hide();
|
||||
} else {
|
||||
this.$more.show();
|
||||
this.$done.addClass('hide');
|
||||
}
|
||||
}
|
||||
|
||||
make_item_card(item) {
|
||||
let $item_card = $(`
|
||||
<div class="hub-item-wrapper" style="max-width: ${this.img_size}px;">
|
||||
<a class="item-link" href>
|
||||
<div class="hub-item-image">
|
||||
${ this.get_item_image(item) }
|
||||
</div>
|
||||
<div class="hub-item-title">
|
||||
<h5 class="bold">
|
||||
${!item.seen ? item.item_name : `<span class="indicator blue">${item.item_name}</span>`}
|
||||
<h5>
|
||||
</div>
|
||||
</a>
|
||||
<div class="company-link">
|
||||
<a data-company-name="${ item.company_name }" class="">${ item.company_name }</a>
|
||||
</div>
|
||||
<div>${ item.formatted_price ? item.formatted_price : ''}</div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
$item_card.find(".item-link").click((e) => {
|
||||
e.preventDefault();
|
||||
this.on_item_click && this.on_item_click(item.name);
|
||||
});
|
||||
|
||||
return $item_card;
|
||||
}
|
||||
|
||||
get_item_image(item, size=this.img_size) {
|
||||
const _size = size + 'px';
|
||||
const item_image = item.image ?
|
||||
`<img src="${item.image}"><span class="helper"></span>` :
|
||||
`<div class="standard-image">${item.item_name[0]}</div>`;
|
||||
|
||||
return `
|
||||
<div class="img-wrapper"
|
||||
style="max-width: ${_size}; width: ${_size}; height: ${_size};">
|
||||
${item_image}
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"content": null,
|
||||
"creation": "2015-02-18 05:17:17.301735",
|
||||
"docstatus": 0,
|
||||
"doctype": "Page",
|
||||
"modified": "2015-02-18 05:17:17.301735",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Hub Node",
|
||||
"name": "hub",
|
||||
"owner": "Administrator",
|
||||
"page_name": "hub",
|
||||
"roles": [
|
||||
{
|
||||
"role": "All"
|
||||
}
|
||||
],
|
||||
"script": null,
|
||||
"standard": "Yes",
|
||||
"style": null,
|
||||
"title": "Hub"
|
||||
}
|
||||
@@ -354,7 +354,8 @@ class BOM(WebsiteGenerator):
|
||||
bom_list = self.traverse_tree(bom_list)
|
||||
for bom in bom_list:
|
||||
bom_obj = frappe.get_doc("BOM", bom)
|
||||
bom_obj.on_update()
|
||||
bom_obj.check_recursion()
|
||||
bom_obj.update_exploded_items()
|
||||
|
||||
return bom_list
|
||||
|
||||
|
||||
@@ -16,16 +16,23 @@ class BOMUpdateTool(Document):
|
||||
self.update_new_bom()
|
||||
bom_list = self.get_parent_boms(self.new_bom)
|
||||
updated_bom = []
|
||||
|
||||
for bom in bom_list:
|
||||
bom_obj = frappe.get_doc("BOM", bom)
|
||||
bom_obj.get_doc_before_save()
|
||||
updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom)
|
||||
bom_obj.calculate_cost()
|
||||
bom_obj.update_parent_cost()
|
||||
bom_obj.db_update()
|
||||
if (getattr(bom_obj.meta, 'track_changes', False)
|
||||
and bom_obj._doc_before_save and not bom_obj.flags.ignore_version):
|
||||
bom_obj.save_version()
|
||||
try:
|
||||
bom_obj = frappe.get_doc("BOM", bom)
|
||||
bom_obj.get_doc_before_save()
|
||||
updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom)
|
||||
bom_obj.calculate_cost()
|
||||
bom_obj.update_parent_cost()
|
||||
bom_obj.db_update()
|
||||
if (getattr(bom_obj.meta, 'track_changes', False)
|
||||
and bom_obj._doc_before_save and not bom_obj.flags.ignore_version):
|
||||
bom_obj.save_version()
|
||||
|
||||
frappe.db.commit()
|
||||
except Exception:
|
||||
frappe.db.rollback()
|
||||
frappe.log_error(frappe.get_traceback())
|
||||
|
||||
def validate_bom(self):
|
||||
if cstr(self.current_bom) == cstr(self.new_bom):
|
||||
@@ -55,14 +62,14 @@ class BOMUpdateTool(Document):
|
||||
bom_list.append(d[0])
|
||||
self.get_parent_boms(d[0], bom_list)
|
||||
|
||||
return bom_list
|
||||
return list(set(bom_list))
|
||||
|
||||
@frappe.whitelist()
|
||||
def enqueue_replace_bom(args):
|
||||
if isinstance(args, string_types):
|
||||
args = json.loads(args)
|
||||
|
||||
frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.replace_bom", args=args)
|
||||
frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.replace_bom", args=args, timeout=4000)
|
||||
frappe.msgprint(_("Queued for replacing the BOM. It may take a few minutes."))
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
@@ -318,7 +318,7 @@ class ProductionOrder(Document):
|
||||
|
||||
from_time, to_time = self.get_start_end_time(timesheet, d.name)
|
||||
|
||||
if date_diff(from_time, original_start_time) > plan_days:
|
||||
if date_diff(from_time, original_start_time) > cint(plan_days):
|
||||
frappe.throw(_("Unable to find Time Slot in the next {0} days for Operation {1}").format(plan_days, d.operation))
|
||||
break
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ Support
|
||||
Utilities
|
||||
Shopping Cart
|
||||
Assets
|
||||
Hub Node
|
||||
Portal
|
||||
Maintenance
|
||||
Education
|
||||
@@ -20,4 +19,4 @@ Healthcare
|
||||
Restaurant
|
||||
Agriculture
|
||||
ERPNext Integrations
|
||||
Non Profit
|
||||
Non Profit
|
||||
|
||||
@@ -502,4 +502,9 @@ erpnext.patches.v10_0.taxes_issue_with_pos
|
||||
erpnext.patches.v10_0.set_qty_in_transactions_based_on_serial_no_input
|
||||
erpnext.patches.v10_0.show_leaves_of_all_department_members_in_calendar
|
||||
erpnext.patches.v10_0.update_status_in_purchase_receipt
|
||||
erpnext.patches.v10_0.update_address_template_for_india
|
||||
erpnext.patches.v10_0.update_address_template_for_india
|
||||
erpnext.patches.v10_0.set_discount_amount
|
||||
erpnext.patches.v10_0.recalculate_gross_margin_for_project
|
||||
erpnext.patches.v10_0.delete_hub_documents
|
||||
erpnext.patches.v10_0.update_user_image_in_employee
|
||||
erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items
|
||||
17
erpnext/patches/v10_0/delete_hub_documents.py
Normal file
17
erpnext/patches/v10_0/delete_hub_documents.py
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
import frappe
|
||||
from frappe.model.utils.rename_field import rename_field
|
||||
|
||||
def execute():
|
||||
for dt, dn in (("Page", "Hub"), ("DocType", "Hub Settings"), ("DocType", "Hub Category")):
|
||||
frappe.delete_doc(dt, dn, ignore_missing=True)
|
||||
|
||||
if frappe.db.exists("DocType", "Data Migration Plan"):
|
||||
data_migration_plans = frappe.get_all("Data Migration Plan", filters={"module": 'Hub Node'})
|
||||
for plan in data_migration_plans:
|
||||
plan_doc = frappe.get_doc("Data Migration Plan", plan.name)
|
||||
for m in plan_doc.get("mappings"):
|
||||
frappe.delete_doc("Data Migration Mapping", m.mapping, force=True)
|
||||
frappe.delete_doc("Data Migration Plan", plan.name)
|
||||
|
||||
frappe.delete_doc("Module Def", "Hub Node", ignore_missing=True)
|
||||
@@ -0,0 +1,14 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('projects', 'doctype', 'project')
|
||||
for d in frappe.db.sql(""" select name from `tabProject` where
|
||||
ifnull(total_consumed_material_cost, 0 ) > 0 and ifnull(total_billed_amount, 0) > 0""", as_dict=1):
|
||||
doc = frappe.get_doc("Project", d.name)
|
||||
doc.calculate_gross_margin()
|
||||
doc.db_set('gross_margin', doc.gross_margin)
|
||||
doc.db_set('per_gross_margin', doc.per_gross_margin)
|
||||
@@ -0,0 +1,32 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
|
||||
def execute():
|
||||
for company in frappe.get_all("Company"):
|
||||
if not erpnext.is_perpetual_inventory_enabled(company.name):
|
||||
continue
|
||||
|
||||
acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto") or "1900-01-01"
|
||||
pr_with_rejected_warehouse = frappe.db.sql("""
|
||||
select pr.name
|
||||
from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
|
||||
where pr.name = pr_item.parent
|
||||
and pr.posting_date > %s
|
||||
and pr.docstatus=1
|
||||
and pr.company = %s
|
||||
and pr_item.rejected_qty > 0
|
||||
""", (acc_frozen_upto, company.name), as_dict=1)
|
||||
|
||||
for d in pr_with_rejected_warehouse:
|
||||
doc = frappe.get_doc("Purchase Receipt", d.name)
|
||||
|
||||
doc.docstatus = 2
|
||||
doc.make_gl_entries_on_cancel(repost_future_gle=False)
|
||||
|
||||
|
||||
# update gl entries for submit state of PR
|
||||
doc.docstatus = 1
|
||||
doc.make_gl_entries(repost_future_gle=False)
|
||||
34
erpnext/patches/v10_0/set_discount_amount.py
Normal file
34
erpnext/patches/v10_0/set_discount_amount.py
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("accounts", "doctype", "sales_invoice_item")
|
||||
frappe.reload_doc('accounts', 'doctype', 'purchase_invoice_item')
|
||||
frappe.reload_doc('buying', 'doctype', 'purchase_order_item')
|
||||
frappe.reload_doc('buying', 'doctype', 'supplier_quotation_item')
|
||||
frappe.reload_doc('selling', 'doctype', 'sales_order_item')
|
||||
frappe.reload_doc('selling', 'doctype', 'quotation_item')
|
||||
frappe.reload_doc('stock', 'doctype', 'delivery_note_item')
|
||||
frappe.reload_doc('stock', 'doctype', 'purchase_receipt_item')
|
||||
|
||||
selling_doctypes = ["Sales Order Item", "Sales Invoice Item", "Delivery Note Item", "Quotation Item"]
|
||||
buying_doctypes = ["Purchase Order Item", "Purchase Invoice Item", "Purchase Receipt Item", "Supplier Quotation Item"]
|
||||
|
||||
for doctype in selling_doctypes:
|
||||
frappe.db.sql('''
|
||||
UPDATE
|
||||
`tab%s`
|
||||
SET
|
||||
discount_amount = if(rate_with_margin > 0, rate_with_margin, price_list_rate) * discount_percentage / 100
|
||||
WHERE
|
||||
discount_percentage > 0
|
||||
''' % (doctype))
|
||||
for doctype in buying_doctypes:
|
||||
frappe.db.sql('''
|
||||
UPDATE
|
||||
`tab%s`
|
||||
SET
|
||||
discount_amount = price_list_rate * discount_percentage / 100
|
||||
WHERE
|
||||
discount_percentage > 0
|
||||
''' % (doctype))
|
||||
@@ -7,7 +7,6 @@ from erpnext.setup.doctype.company.company import install_country_fixtures
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("accounts", "doctype", "account")
|
||||
frappe.reload_doc("hub_node", "doctype", "hub_category")
|
||||
frappe.reload_doc("accounts", "doctype", "payment_schedule")
|
||||
for d in frappe.get_all('Company',
|
||||
filters={'country': ('in', ['Saudi Arabia', 'United Arab Emirates'])}):
|
||||
|
||||
19
erpnext/patches/v10_0/update_user_image_in_employee.py
Normal file
19
erpnext/patches/v10_0/update_user_image_in_employee.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('hr', 'doctype', 'employee')
|
||||
|
||||
frappe.db.sql("""
|
||||
UPDATE
|
||||
`tabEmployee`, `tabUser`
|
||||
SET
|
||||
`tabEmployee`.image = `tabUser`.user_image
|
||||
WHERE
|
||||
`tabEmployee`.user_id = `tabUser`.name and
|
||||
`tabEmployee`.user_id is not null and
|
||||
`tabEmployee`.user_id != '' and `tabEmployee`.image is null
|
||||
""")
|
||||
@@ -4,7 +4,6 @@ from frappe.email import sendmail_to_system_managers
|
||||
def execute():
|
||||
frappe.reload_doc('stock', 'doctype', 'item')
|
||||
frappe.reload_doc("stock", "doctype", "customs_tariff_number")
|
||||
frappe.reload_doc("hub_node", "doctype", "hub_category")
|
||||
frappe.reload_doc("accounts", "doctype", "payment_terms_template")
|
||||
frappe.reload_doc("accounts", "doctype", "payment_schedule")
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -41,10 +42,43 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"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,
|
||||
@@ -71,10 +105,75 @@
|
||||
"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": "show_availability_status",
|
||||
"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": "Show Availability Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -103,6 +202,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@@ -116,7 +216,7 @@
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-07 19:34:33.055048",
|
||||
"modified": "2018-08-14 17:59:58.473100",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Portal",
|
||||
"name": "Products Settings",
|
||||
|
||||
@@ -52,7 +52,14 @@ class Project(Document):
|
||||
if self.name is None:
|
||||
return {}
|
||||
else:
|
||||
return frappe.get_all("Task", "*", {"project": self.name}, order_by="exp_start_date asc")
|
||||
filters = {"project": self.name}
|
||||
|
||||
if self.get("deleted_task_list"):
|
||||
filters.update({
|
||||
'name': ("not in", self.deleted_task_list)
|
||||
})
|
||||
|
||||
return frappe.get_all("Task", "*", filters, order_by="exp_start_date asc")
|
||||
|
||||
def validate(self):
|
||||
self.validate_project_name()
|
||||
@@ -62,6 +69,7 @@ class Project(Document):
|
||||
self.tasks = []
|
||||
self.load_tasks()
|
||||
self.send_welcome_email()
|
||||
self.update_percent_complete()
|
||||
|
||||
def validate_project_name(self):
|
||||
if self.get("__islocal") and frappe.db.exists("Project", self.project_name):
|
||||
@@ -82,12 +90,26 @@ class Project(Document):
|
||||
|
||||
def sync_tasks(self):
|
||||
"""sync tasks and remove table"""
|
||||
if not hasattr(self, "deleted_task_list"):
|
||||
self.set("deleted_task_list", [])
|
||||
|
||||
if self.flags.dont_sync_tasks: return
|
||||
task_names = []
|
||||
|
||||
existing_task_data = {}
|
||||
|
||||
fields = ["title", "status", "start_date", "end_date", "description", "task_weight", "task_id"]
|
||||
exclude_fieldtype = ["Button", "Column Break",
|
||||
"Section Break", "Table", "Read Only", "Attach", "Attach Image", "Color", "Geolocation", "HTML", "Image"]
|
||||
|
||||
custom_fields = frappe.get_all("Custom Field", {"dt": "Project Task",
|
||||
"fieldtype": ("not in", exclude_fieldtype)}, "fieldname")
|
||||
|
||||
for d in custom_fields:
|
||||
fields.append(d.fieldname)
|
||||
|
||||
for d in frappe.get_all('Project Task',
|
||||
fields = ["title", "status", "start_date", "end_date", "description", "task_weight", "task_id"],
|
||||
fields = fields,
|
||||
filters = {'parent': self.name}):
|
||||
existing_task_data.setdefault(d.task_id, d)
|
||||
|
||||
@@ -98,7 +120,7 @@ class Project(Document):
|
||||
task = frappe.new_doc("Task")
|
||||
task.project = self.name
|
||||
|
||||
if not t.task_id or self.is_row_updated(t, existing_task_data):
|
||||
if not t.task_id or self.is_row_updated(t, existing_task_data, fields):
|
||||
task.update({
|
||||
"subject": t.title,
|
||||
"status": t.status,
|
||||
@@ -120,7 +142,7 @@ class Project(Document):
|
||||
"modified": now()
|
||||
})
|
||||
|
||||
task.validate()
|
||||
task.run_method("validate")
|
||||
task.db_update()
|
||||
else:
|
||||
task.save(ignore_permissions = True)
|
||||
@@ -130,21 +152,20 @@ class Project(Document):
|
||||
|
||||
# delete
|
||||
for t in frappe.get_all("Task", ["name"], {"project": self.name, "name": ("not in", task_names)}):
|
||||
frappe.delete_doc("Task", t.name)
|
||||
self.deleted_task_list.append(t.name)
|
||||
|
||||
def update_costing_and_percentage_complete(self):
|
||||
self.update_percent_complete()
|
||||
self.update_costing()
|
||||
|
||||
def is_row_updated(self, row, existing_task_data):
|
||||
def is_row_updated(self, row, existing_task_data, fields):
|
||||
if self.get("__islocal") or not existing_task_data: return True
|
||||
|
||||
d = existing_task_data.get(row.task_id)
|
||||
|
||||
if (d and (row.title != d.title or row.status != d.status
|
||||
or getdate(row.start_date) != getdate(d.start_date) or getdate(row.end_date) != getdate(d.end_date)
|
||||
or row.description != d.description or row.task_weight != d.task_weight)):
|
||||
return True
|
||||
for field in fields:
|
||||
if row.get(field) != d.get(field):
|
||||
return True
|
||||
|
||||
def map_custom_fields(self, source, target):
|
||||
project_task_custom_fields = frappe.get_all("Custom Field", {"dt": "Project Task"}, "fieldname")
|
||||
@@ -216,9 +237,13 @@ class Project(Document):
|
||||
self.update_purchase_costing()
|
||||
self.update_sales_amount()
|
||||
self.update_billed_amount()
|
||||
self.calculate_gross_margin()
|
||||
|
||||
self.gross_margin = flt(self.total_billed_amount) - (flt(self.total_costing_amount) + flt(self.total_expense_claim) + flt(self.total_purchase_cost))
|
||||
def calculate_gross_margin(self):
|
||||
expense_amount = (flt(self.total_costing_amount) + flt(self.total_expense_claim)
|
||||
+ flt(self.total_purchase_cost) + flt(self.get('total_consumed_material_cost', 0)))
|
||||
|
||||
self.gross_margin = flt(self.total_billed_amount) - expense_amount
|
||||
if self.total_billed_amount:
|
||||
self.per_gross_margin = (self.gross_margin / flt(self.total_billed_amount)) *100
|
||||
|
||||
@@ -263,9 +288,19 @@ class Project(Document):
|
||||
user.welcome_email_sent=1
|
||||
|
||||
def on_update(self):
|
||||
self.delete_task()
|
||||
self.load_tasks()
|
||||
self.update_costing_and_percentage_complete()
|
||||
self.update_dependencies_on_duplicated_project()
|
||||
|
||||
def delete_task(self):
|
||||
if not self.get('deleted_task_list'): return
|
||||
|
||||
for d in self.get('deleted_task_list'):
|
||||
frappe.delete_doc("Task", d)
|
||||
|
||||
self.deleted_task_list = []
|
||||
|
||||
def update_dependencies_on_duplicated_project(self):
|
||||
if self.flags.dont_sync_tasks: return
|
||||
if not self.copied_from:
|
||||
|
||||
@@ -26,6 +26,11 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
};
|
||||
});
|
||||
|
||||
if (this.frm.doc.__islocal
|
||||
&& frappe.meta.has_field(this.frm.doc.doctype, "disable_rounded_total")) {
|
||||
this.frm.set_value("disable_rounded_total", cint(frappe.sys_defaults.disable_rounded_total));
|
||||
}
|
||||
|
||||
/* eslint-disable */
|
||||
// no idea where me is coming from
|
||||
if(this.frm.get_field('shipping_address')) {
|
||||
@@ -108,8 +113,8 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
var item = frappe.get_doc(cdt, cdn);
|
||||
frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]);
|
||||
|
||||
item.rate = flt(item.price_list_rate * (1 - item.discount_percentage / 100.0),
|
||||
precision("rate", item));
|
||||
item.discount_amount = flt(item.price_list_rate) * flt(item.discount_percentage) / 100;
|
||||
item.rate = flt((item.price_list_rate) - (item.discount_amount), precision('rate', item));
|
||||
|
||||
this.calculate_taxes_and_totals();
|
||||
},
|
||||
@@ -222,6 +227,69 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
|
||||
tc_name: function() {
|
||||
this.get_terms();
|
||||
},
|
||||
|
||||
link_to_mrs: function() {
|
||||
var my_items = [];
|
||||
for (var i in cur_frm.doc.items) {
|
||||
if(!cur_frm.doc.items[i].material_request){
|
||||
my_items.push(cur_frm.doc.items[i].item_code);
|
||||
}
|
||||
}
|
||||
frappe.call({
|
||||
method: "erpnext.buying.utils.get_linked_material_requests",
|
||||
args:{
|
||||
items: my_items
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.message) {
|
||||
frappe.throw(__("No pending Material Requests found to link for the given items."))
|
||||
}
|
||||
else {
|
||||
var i = 0;
|
||||
var item_length = cur_frm.doc.items.length;
|
||||
while (i < item_length) {
|
||||
var qty = cur_frm.doc.items[i].qty;
|
||||
(r.message[0] || []).forEach(function(d) {
|
||||
if (d.qty > 0 && qty > 0 && cur_frm.doc.items[i].item_code == d.item_code && !cur_frm.doc.items[i].material_request_item)
|
||||
{
|
||||
cur_frm.doc.items[i].material_request = d.mr_name;
|
||||
cur_frm.doc.items[i].material_request_item = d.mr_item;
|
||||
var my_qty = Math.min(qty, d.qty);
|
||||
qty = qty - my_qty;
|
||||
d.qty = d.qty - my_qty;
|
||||
cur_frm.doc.items[i].stock_qty = my_qty*cur_frm.doc.items[i].conversion_factor;
|
||||
cur_frm.doc.items[i].qty = my_qty;
|
||||
|
||||
frappe.msgprint("Assigning " + d.mr_name + " to " + d.item_code + " (row " + cur_frm.doc.items[i].idx + ")");
|
||||
if (qty > 0)
|
||||
{
|
||||
frappe.msgprint("Splitting " + qty + " units of " + d.item_code);
|
||||
var newrow = frappe.model.add_child(cur_frm.doc, cur_frm.doc.items[i].doctype, "items");
|
||||
item_length++;
|
||||
|
||||
for (var key in cur_frm.doc.items[i])
|
||||
{
|
||||
newrow[key] = cur_frm.doc.items[i][key];
|
||||
}
|
||||
|
||||
newrow.idx = item_length;
|
||||
newrow["stock_qty"] = newrow.conversion_factor*qty;
|
||||
newrow["qty"] = qty;
|
||||
|
||||
newrow["material_request"] = "";
|
||||
newrow["material_request_item"] = "";
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
i++;
|
||||
}
|
||||
refresh_field("items");
|
||||
//cur_frm.save();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
||||
item.rate = flt(item.rate_with_margin , precision("rate", item));
|
||||
|
||||
if(item.discount_percentage){
|
||||
var discount_value = flt(item.rate_with_margin) * flt(item.discount_percentage) / 100;
|
||||
item.rate = flt((item.rate_with_margin) - (discount_value), precision('rate', item));
|
||||
item.discount_amount = flt(item.rate_with_margin) * flt(item.discount_percentage) / 100;
|
||||
item.rate = flt((item.rate_with_margin) - (item.discount_amount), precision('rate', item));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
{% for(var j=i*3; j
|
||||
<(i+1)*3; j++) { %} <button type="button" class="btn btn-default numeric-keypad" val="{{j+1}}">{{j+1}}</button>
|
||||
{% } %}
|
||||
<button type="button" {% if((!allow_user_to_edit_rate && chartData[i] == __("Price")) || (!allow_user_to_edit_discount && chartData[i] == __("Disc"))) { %} disabled {% } %} id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ __(chartData[i]) }}</button>
|
||||
<button type="button" {% if((!allow_user_to_edit_rate && __(chartData[i]) == __("Price")) || (!allow_user_to_edit_discount && __(chartData[i]) == __("Disc"))) { %} disabled {% } %} id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ __(chartData[i]) }}</button>
|
||||
</div>
|
||||
{% } %}
|
||||
<div class="row text-right">
|
||||
|
||||
@@ -138,10 +138,15 @@ erpnext.setup.slides_settings = [
|
||||
|
||||
validate: function () {
|
||||
// validate fiscal year start and end dates
|
||||
if (this.values.fy_start_date == 'Invalid date' || this.values.fy_end_date == 'Invalid date') {
|
||||
const invalid = this.values.fy_start_date == 'Invalid date' ||
|
||||
this.values.fy_end_date == 'Invalid date';
|
||||
const start_greater_than_end = this.values.fy_start_date > this.values.fy_end_date;
|
||||
|
||||
if (invalid || start_greater_than_end) {
|
||||
frappe.msgprint(__("Please enter valid Financial Year Start and End Dates"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
@@ -412,6 +412,12 @@ body[data-route="pos"] {
|
||||
.collapse-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (max-width: @screen-xs) {
|
||||
.page-actions {
|
||||
max-width: 110px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.price-info {
|
||||
|
||||
@@ -790,6 +790,38 @@
|
||||
"unique": 0,
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "discount_percentage",
|
||||
"fieldname": "discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Discount Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -1766,7 +1798,7 @@
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2017-12-14 09:39:17.180709",
|
||||
"modified": "2018-08-06 05:18:38.135668",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Quotation Item",
|
||||
|
||||
@@ -820,6 +820,38 @@
|
||||
"unique": 0,
|
||||
"width": "70px"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "discount_percentage",
|
||||
"fieldname": "discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Discount Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -2146,7 +2178,7 @@
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2017-11-30 14:05:39.173834",
|
||||
"modified": "2018-08-06 05:17:51.297862",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order Item",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user