mirror of
https://github.com/frappe/erpnext.git
synced 2026-07-20 11:22:28 +00:00
Compare commits
113 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '10.1.46'
|
||||
__version__ = '10.1.64'
|
||||
|
||||
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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -641,7 +641,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,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -161,21 +161,21 @@
|
||||
</td>
|
||||
{% } %}
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Invoiced Amount"], data[i]["currency"]) %}</td>
|
||||
{%= format_currency(data[i]["invoiced_amount"], data[i]["currency"]) %}</td>
|
||||
|
||||
{% if(!filters.show_pdc_in_print) { %}
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Paid Amount"], data[i]["currency"]) %}</td>
|
||||
{%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">
|
||||
{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["Credit Note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %}</td>
|
||||
{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["debit_note"], data[i]["currency"]) %}</td>
|
||||
{% } %}
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Outstanding Amount"], data[i]["currency"]) %}</td>
|
||||
{%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %}</td>
|
||||
|
||||
{% if(filters.show_pdc_in_print) { %}
|
||||
{% if(report.report_name === "Accounts Receivable") { %}
|
||||
<td style="text-align: right">
|
||||
{%= data[i][__("Customer LPO")] %}</td>
|
||||
{%= data[i]["po_no"] %}</td>
|
||||
{% } %}
|
||||
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][__("PDC/LC Date")]) %}</td>
|
||||
<td style="text-align: right">{%= data[i][__("PDC/LC Ref")] %}</td>
|
||||
@@ -189,15 +189,15 @@
|
||||
{% } %}
|
||||
<td><b>{%= __("Total") %}</b></td>
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Invoiced Amount"], data[i]["currency"] ) %}</td>
|
||||
{%= format_currency(data[i]["invoiced_amount"], data[i]["currency"] ) %}</td>
|
||||
|
||||
{% if(!filters.show_pdc_in_print) { %}
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Paid Amount"], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["Credit Note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %} </td>
|
||||
{%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %}</td>
|
||||
<td style="text-align: right">{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %} </td>
|
||||
{% } %}
|
||||
<td style="text-align: right">
|
||||
{%= format_currency(data[i]["Outstanding Amount"], data[i]["currency"]) %}</td>
|
||||
{%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %}</td>
|
||||
|
||||
{% if(filters.show_pdc_in_print) { %}
|
||||
{% if(report.report_name === "Accounts Receivable") { %}
|
||||
@@ -238,4 +238,4 @@
|
||||
{% } %}
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="text-right text-muted">{{ __("Printed On ") }}{%= 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
|
||||
@@ -103,9 +104,13 @@ class ReceivablePayableReport(object):
|
||||
]
|
||||
|
||||
if args.get('party_type') == 'Customer':
|
||||
columns += [_("Customer LPO") + ":Data:100"]
|
||||
columns.append({
|
||||
"label": _("Customer LPO"),
|
||||
"fieldtype": "Data",
|
||||
"fieldname": "po_no",
|
||||
"width": 100,
|
||||
})
|
||||
columns += [_("Delivery Note") + ":Data:100"]
|
||||
|
||||
if args.get("party_type") == "Customer":
|
||||
columns += [
|
||||
_("Territory") + ":Link/Territory:80",
|
||||
@@ -123,9 +128,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"):
|
||||
@@ -138,7 +140,14 @@ class ReceivablePayableReport(object):
|
||||
data = []
|
||||
pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date)
|
||||
|
||||
for gle in self.get_entries_till(self.filters.report_date, args.get("party_type")):
|
||||
gl_entries_data = 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)
|
||||
@@ -171,7 +180,7 @@ class ReceivablePayableReport(object):
|
||||
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
|
||||
entry_date = bill_date
|
||||
else:
|
||||
entry_date = gle.posting_date
|
||||
row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2),
|
||||
@@ -218,12 +227,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 (
|
||||
@@ -250,14 +258,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
|
||||
@@ -286,42 +296,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
|
||||
|
||||
@@ -457,18 +456,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)
|
||||
|
||||
|
||||
@@ -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', {
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
@@ -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",
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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,8 @@ 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
|
||||
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)
|
||||
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,
|
||||
@@ -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,7 +26,8 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
};
|
||||
});
|
||||
|
||||
if (this.frm.doc.__islocal) {
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -112,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();
|
||||
},
|
||||
@@ -226,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;
|
||||
},
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -5,6 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import msgprint, _
|
||||
from frappe.utils import flt
|
||||
from erpnext import get_company_currency
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
@@ -14,12 +15,14 @@ def execute(filters=None):
|
||||
item_details = get_item_details()
|
||||
data = []
|
||||
|
||||
company_currency = get_company_currency(filters["company"])
|
||||
|
||||
for d in entries:
|
||||
if d.stock_qty > 0 or filters.get('show_return_entries', 0):
|
||||
data.append([
|
||||
d.name, d.customer, d.territory, d.posting_date, d.item_code,
|
||||
d.name, d.customer, d.territory, d.warehouse, d.posting_date, d.item_code,
|
||||
item_details.get(d.item_code, {}).get("item_group"), item_details.get(d.item_code, {}).get("brand"),
|
||||
d.stock_qty, d.base_net_amount, d.sales_person, d.allocated_percentage, d.contribution_amt
|
||||
d.stock_qty, d.base_net_amount, d.sales_person, d.allocated_percentage, d.contribution_amt, company_currency
|
||||
])
|
||||
|
||||
if data:
|
||||
@@ -32,12 +35,105 @@ def get_columns(filters):
|
||||
if not filters.get("doc_type"):
|
||||
msgprint(_("Please select the document type first"), raise_exception=1)
|
||||
|
||||
return [filters["doc_type"] + ":Link/" + filters["doc_type"] + ":140",
|
||||
_("Customer") + ":Link/Customer:140", _("Territory") + ":Link/Territory:100", _("Posting Date") + ":Date:100",
|
||||
_("Item Code") + ":Link/Item:120", _("Item Group") + ":Link/Item Group:120",
|
||||
_("Brand") + ":Link/Brand:120", _("Qty") + ":Float:100", _("Amount") + ":Currency:120",
|
||||
_("Sales Person") + ":Link/Sales Person:140", _("Contribution %") + "::110",
|
||||
_("Contribution Amount") + ":Currency:140"]
|
||||
columns = [
|
||||
{
|
||||
"label": _(filters["doc_type"]),
|
||||
"options": filters["doc_type"],
|
||||
"fieldname": frappe.scrub(filters['doc_type']),
|
||||
"fieldtype": "Link",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Customer"),
|
||||
"options": "Customer",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Territory"),
|
||||
"options": "Territory",
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Warehouse"),
|
||||
"options": "Warehouse",
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Posting Date"),
|
||||
"fieldname": "posting_date",
|
||||
"fieldtype": "Date",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Item Code"),
|
||||
"options": "Item",
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Item Group"),
|
||||
"options": "Item Group",
|
||||
"fieldname": "item_group",
|
||||
"fieldtype": "Link",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Brand"),
|
||||
"options": "Brand",
|
||||
"fieldname": "brand",
|
||||
"fieldtype": "Link",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Qty"),
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Amount"),
|
||||
"options": "currency",
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Sales Person"),
|
||||
"options": "Sales Person",
|
||||
"fieldname": "sales_person",
|
||||
"fieldtype": "Link",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Contribution %"),
|
||||
"fieldname": "contribution",
|
||||
"fieldtype": "Float",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("Contribution Amount"),
|
||||
"options": "currency",
|
||||
"fieldname": "contribution_amt",
|
||||
"fieldtype": "Currency",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label":_("Currency"),
|
||||
"options": "Currency",
|
||||
"fieldname":"currency",
|
||||
"fieldtype":"Link",
|
||||
"hidden" : 1
|
||||
}
|
||||
]
|
||||
|
||||
return columns
|
||||
|
||||
def get_entries(filters):
|
||||
date_field = filters["doc_type"] == "Sales Order" and "transaction_date" or "posting_date"
|
||||
@@ -48,10 +144,10 @@ def get_entries(filters):
|
||||
conditions, values = get_conditions(filters, date_field)
|
||||
|
||||
entries = frappe.db.sql("""
|
||||
select
|
||||
SELECT
|
||||
dt.name, dt.customer, dt.territory, dt.%s as posting_date, dt_item.item_code,
|
||||
st.sales_person, st.allocated_percentage,
|
||||
CASE
|
||||
st.sales_person, st.allocated_percentage, dt_item.warehouse,
|
||||
CASE
|
||||
WHEN dt.status = "Closed" THEN dt_item.%s * dt_item.conversion_factor
|
||||
ELSE dt_item.stock_qty
|
||||
END as stock_qty,
|
||||
@@ -63,9 +159,9 @@ def get_entries(filters):
|
||||
WHEN dt.status = "Closed" THEN ((dt_item.base_net_rate * dt_item.%s * dt_item.conversion_factor) * st.allocated_percentage/100)
|
||||
ELSE dt_item.base_net_amount * st.allocated_percentage/100
|
||||
END as contribution_amt
|
||||
from
|
||||
FROM
|
||||
`tab%s` dt, `tab%s Item` dt_item, `tabSales Team` st
|
||||
where
|
||||
WHERE
|
||||
st.parent = dt.name and dt.name = dt_item.parent and st.parenttype = %s
|
||||
and dt.docstatus = 1 %s order by st.sales_person, dt.name desc
|
||||
""" %(date_field, qty_field, qty_field, qty_field, filters["doc_type"], filters["doc_type"], '%s', conditions),
|
||||
@@ -115,7 +211,7 @@ def get_items(filters):
|
||||
|
||||
def get_item_details():
|
||||
item_details = {}
|
||||
for d in frappe.db.sql("""select name, item_group, brand from `tabItem`""", as_dict=1):
|
||||
for d in frappe.db.sql("""SELECT `name`, `item_group`, `brand` FROM `tabItem`""", as_dict=1):
|
||||
item_details.setdefault(d.name, d)
|
||||
|
||||
return item_details
|
||||
|
||||
@@ -138,6 +138,9 @@ def get_item_for_list_in_html(context):
|
||||
if (context.get("website_image") or "").startswith("files/"):
|
||||
context["website_image"] = "/" + urllib.quote(context["website_image"])
|
||||
|
||||
context["show_availability_status"] = cint(frappe.db.get_single_value('Products Settings',
|
||||
'show_availability_status'))
|
||||
|
||||
products_template = 'templates/includes/products_as_grid.html'
|
||||
if cint(frappe.db.get_single_value('Products Settings', 'products_as_list')):
|
||||
products_template = 'templates/includes/products_as_list.html'
|
||||
|
||||
@@ -30,7 +30,7 @@ def make_tax_account_and_template(company, account_name, tax_rate, template_name
|
||||
if accounts:
|
||||
make_sales_and_purchase_tax_templates(accounts, template_name)
|
||||
except frappe.NameError:
|
||||
frappe.message_log.pop()
|
||||
if frappe.message_log: frappe.message_log.pop()
|
||||
except RootNotEditable:
|
||||
pass
|
||||
|
||||
@@ -50,7 +50,7 @@ def make_tax_account(company, account_name, tax_rate):
|
||||
"tax_rate": flt(tax_rate) if tax_rate else None
|
||||
}).insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
except frappe.NameError:
|
||||
frappe.message_log.pop()
|
||||
if frappe.message_log: frappe.message_log.pop()
|
||||
abbr = frappe.db.get_value('Company', company, 'abbr')
|
||||
account = '{0} - {1}'.format(account_name, abbr)
|
||||
return frappe.get_doc('Account', account)
|
||||
|
||||
@@ -255,13 +255,13 @@ erpnext.stock.delivery_note.set_print_hide = function(doc, cdt, cdn){
|
||||
var dn_item_fields = frappe.meta.docfield_map['Delivery Note Item'];
|
||||
var dn_fields_copy = dn_fields;
|
||||
var dn_item_fields_copy = dn_item_fields;
|
||||
|
||||
if (doc.print_without_amount) {
|
||||
dn_fields['currency'].print_hide = 1;
|
||||
dn_item_fields['rate'].print_hide = 1;
|
||||
dn_item_fields['discount_percentage'].print_hide = 1;
|
||||
dn_item_fields['price_list_rate'].print_hide = 1;
|
||||
dn_item_fields['amount'].print_hide = 1;
|
||||
dn_item_fields['discount_amount'].print_hide = 1;
|
||||
dn_fields['taxes'].print_hide = 1;
|
||||
} else {
|
||||
if (dn_fields_copy['currency'].print_hide != 1)
|
||||
@@ -270,6 +270,8 @@ erpnext.stock.delivery_note.set_print_hide = function(doc, cdt, cdn){
|
||||
dn_item_fields['rate'].print_hide = 0;
|
||||
if (dn_item_fields_copy['amount'].print_hide != 1)
|
||||
dn_item_fields['amount'].print_hide = 0;
|
||||
if (dn_item_fields_copy['discount_amount'].print_hide != 1)
|
||||
dn_item_fields['discount_amount'].print_hide = 0;
|
||||
if (dn_fields_copy['taxes'].print_hide != 1)
|
||||
dn_fields['taxes'].print_hide = 0;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ class DeliveryNote(SellingController):
|
||||
item_meta = frappe.get_meta("Delivery Note Item")
|
||||
print_hide_fields = {
|
||||
"parent": ["grand_total", "rounded_total", "in_words", "currency", "total", "taxes"],
|
||||
"items": ["rate", "amount", "price_list_rate", "discount_percentage"]
|
||||
"items": ["rate", "amount", "discount_amount", "price_list_rate", "discount_percentage"]
|
||||
}
|
||||
|
||||
for key, fieldname in print_hide_fields.items():
|
||||
|
||||
@@ -819,6 +819,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,
|
||||
@@ -2139,7 +2171,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-30 14:07:12.217563",
|
||||
"modified": "2018-08-06 05:18:26.132899",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Delivery Note Item",
|
||||
|
||||
@@ -3451,38 +3451,6 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "hub_category_to_publish",
|
||||
"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": "Hub Category to Publish",
|
||||
"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,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -3561,7 +3529,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 1,
|
||||
"modified": "2018-04-11 12:21:48.715529",
|
||||
"modified": "2018-09-06 14:45:48.715529",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Item",
|
||||
|
||||
@@ -6,7 +6,8 @@ def get_data():
|
||||
'non_standard_fieldnames': {
|
||||
'Purchase Invoice': 'purchase_receipt',
|
||||
'Landed Cost Voucher': 'receipt_document',
|
||||
'Subscription': 'reference_document'
|
||||
'Subscription': 'reference_document',
|
||||
'Purchase Receipt': 'return_against'
|
||||
},
|
||||
'internal_links': {
|
||||
'Purchase Order': ['items', 'purchase_order'],
|
||||
@@ -24,7 +25,7 @@ def get_data():
|
||||
},
|
||||
{
|
||||
'label': _('Returns'),
|
||||
'items': ['Stock Entry']
|
||||
'items': ['Purchase Receipt']
|
||||
},
|
||||
{
|
||||
'label': _('Subscription'),
|
||||
|
||||
@@ -759,6 +759,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,
|
||||
@@ -2290,7 +2322,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-06 13:50:08.201145",
|
||||
"modified": "2018-08-06 05:16:48.590787",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt Item",
|
||||
|
||||
@@ -187,13 +187,14 @@ def process_serial_no(sle):
|
||||
update_serial_nos(sle, item_det)
|
||||
|
||||
def validate_serial_no(sle, item_det):
|
||||
serial_nos = get_serial_nos(sle.serial_no) if sle.serial_no else []
|
||||
|
||||
if item_det.has_serial_no==0:
|
||||
if sle.serial_no:
|
||||
if serial_nos:
|
||||
frappe.throw(_("Item {0} is not setup for Serial Nos. Column must be blank").format(sle.item_code),
|
||||
SerialNoNotRequiredError)
|
||||
elif sle.is_cancelled == "No":
|
||||
if sle.serial_no:
|
||||
serial_nos = get_serial_nos(sle.serial_no)
|
||||
if serial_nos:
|
||||
if cint(sle.actual_qty) != flt(sle.actual_qty):
|
||||
frappe.throw(_("Serial No {0} quantity {1} cannot be a fraction").format(sle.item_code, sle.actual_qty))
|
||||
|
||||
@@ -239,6 +240,12 @@ def validate_serial_no(sle, item_det):
|
||||
elif sle.actual_qty < 0 or not item_det.serial_no_series:
|
||||
frappe.throw(_("Serial Nos Required for Serialized Item {0}").format(sle.item_code),
|
||||
SerialNoRequiredError)
|
||||
elif serial_nos:
|
||||
for serial_no in serial_nos:
|
||||
sr = frappe.db.get_value("Serial No", serial_no, ["name", "warehouse"], as_dict=1)
|
||||
if sr and sle.actual_qty < 0 and sr.warehouse != sle.warehouse:
|
||||
frappe.throw(_("Cannot cancel {0} {1} because Serial No {2} does not belong to the warehouse {3}")
|
||||
.format(sle.voucher_type, sle.voucher_no, serial_no, sle.warehouse))
|
||||
|
||||
def has_duplicate_serial_no(sn, sle):
|
||||
if sn.warehouse:
|
||||
|
||||
@@ -82,6 +82,7 @@ class StockEntry(StockController):
|
||||
if self.purchase_order and self.purpose == "Subcontract":
|
||||
self.update_purchase_order_supplied_items()
|
||||
self.make_gl_entries_on_cancel()
|
||||
self.update_cost_in_project()
|
||||
|
||||
def validate_purpose(self):
|
||||
valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer", "Material Transfer for Manufacture",
|
||||
@@ -107,8 +108,18 @@ class StockEntry(StockController):
|
||||
se.docstatus = 1 and se.project = %s and sed.parent = se.name
|
||||
and (sed.t_warehouse is null or sed.t_warehouse = '')""", self.project, as_list=1)
|
||||
|
||||
if amount:
|
||||
frappe.db.set_value('Project', self.project, 'total_consumed_material_cost', amount[0][0])
|
||||
amount = amount[0][0] if amount else 0
|
||||
additional_costs = frappe.db.sql(""" select ifnull(sum(sed.amount), 0)
|
||||
from
|
||||
`tabStock Entry` se, `tabLanded Cost Taxes and Charges` sed
|
||||
where
|
||||
se.docstatus = 1 and se.project = %s and sed.parent = se.name
|
||||
and se.purpose = 'Manufacture'""", self.project, as_list=1)
|
||||
|
||||
additional_cost_amt = additional_costs[0][0] if additional_costs else 0
|
||||
|
||||
amount += additional_cost_amt
|
||||
frappe.db.set_value('Project', self.project, 'total_consumed_material_cost', amount)
|
||||
|
||||
def validate_item(self):
|
||||
stock_items = self.get_stock_items()
|
||||
|
||||
@@ -109,7 +109,7 @@ class StockReconciliation(StockController):
|
||||
self.validation_messages.append(_get_msg(row_num,
|
||||
_("Negative Valuation Rate is not allowed")))
|
||||
|
||||
if row.qty and not row.valuation_rate:
|
||||
if row.qty and row.valuation_rate in ["", None]:
|
||||
row.valuation_rate = get_stock_balance(row.item_code, row.warehouse,
|
||||
self.posting_date, self.posting_time, with_valuation_rate=True)[1]
|
||||
if not row.valuation_rate:
|
||||
|
||||
@@ -139,7 +139,7 @@ class Warehouse(NestedSet):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, company=None, is_root=False):
|
||||
from erpnext.stock.utils import get_stock_value_on
|
||||
from erpnext.stock.utils import get_stock_value_from_bin
|
||||
|
||||
if is_root:
|
||||
parent = ""
|
||||
@@ -154,7 +154,7 @@ def get_children(doctype, parent=None, company=None, is_root=False):
|
||||
|
||||
# return warehouses
|
||||
for wh in warehouses:
|
||||
wh["balance"] = get_stock_value_on(warehouse=wh.value)
|
||||
wh["balance"] = get_stock_value_from_bin(warehouse=wh.value)
|
||||
return warehouses
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -170,4 +170,4 @@ def add_node():
|
||||
@frappe.whitelist()
|
||||
def convert_to_group_or_ledger():
|
||||
args = frappe.form_dict
|
||||
return frappe.get_doc("Warehouse", args.docname).convert_to_group_or_ledger()
|
||||
return frappe.get_doc("Warehouse", args.docname).convert_to_group_or_ledger()
|
||||
|
||||
@@ -481,8 +481,8 @@ def get_projected_qty(item_code, warehouse):
|
||||
@frappe.whitelist()
|
||||
def get_bin_details(item_code, warehouse):
|
||||
return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
|
||||
["projected_qty", "actual_qty"], as_dict=True) \
|
||||
or {"projected_qty": 0, "actual_qty": 0}
|
||||
["projected_qty", "actual_qty", "reserved_qty"], as_dict=True) \
|
||||
or {"projected_qty": 0, "actual_qty": 0, "reserved_qty": 0}
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_serial_no_details(item_code, warehouse, stock_qty, serial_no):
|
||||
|
||||
@@ -13,12 +13,18 @@ def execute(filters=None):
|
||||
def get_columns():
|
||||
return [
|
||||
{
|
||||
"label": _("Item Name"),
|
||||
"fieldname": "item_name",
|
||||
"label": _("Item Code"),
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"options": "Item",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"label": _("Item Name"),
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"label": _("Warehouse"),
|
||||
"fieldname": "warehouse",
|
||||
@@ -70,7 +76,7 @@ def get_item_price_qty_data(filters):
|
||||
if filters.get("item_code"):
|
||||
conditions += "where a.item_code=%(item_code)s"
|
||||
|
||||
item_results = frappe.db.sql("""select a.item_code as item_name, a.name as price_list_name,
|
||||
item_results = frappe.db.sql("""select a.item_code, a.item_name, a.name as price_list_name,
|
||||
b.warehouse as warehouse, b.actual_qty as actual_qty
|
||||
from `tabItem Price` a left join `tabBin` b
|
||||
ON a.item_code = b.item_code
|
||||
@@ -86,6 +92,7 @@ def get_item_price_qty_data(filters):
|
||||
if item_results:
|
||||
for item_dict in item_results:
|
||||
data = {
|
||||
'item_code': item_dict.item_code,
|
||||
'item_name': item_dict.item_name,
|
||||
'warehouse': item_dict.warehouse,
|
||||
'stock_available': item_dict.actual_qty or 0,
|
||||
|
||||
@@ -33,7 +33,7 @@ def execute(filters=None):
|
||||
|
||||
row = [cd.item_code, cd.item_name, cd.description, cd.stock_uom, \
|
||||
consumed_qty, consumed_amount, delivered_qty, delivered_amount, \
|
||||
total_qty, total_amount, list(set(suppliers))]
|
||||
total_qty, total_amount, ','.join(list(set(suppliers)))]
|
||||
data.append(row)
|
||||
|
||||
return columns, data
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user