Merge branch 'develop'
This commit is contained in:
commit
1d621be1f7
@ -1,2 +1,2 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
__version__ = '6.2.0'
|
__version__ = '6.3.0'
|
||||||
|
@ -44,7 +44,7 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function() {
|
refresh: function() {
|
||||||
this.frm.disable_save();
|
this.frm.disable_save();
|
||||||
},
|
},
|
||||||
@ -77,8 +77,8 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
|
|||||||
var invoices = [];
|
var invoices = [];
|
||||||
|
|
||||||
$.each(me.frm.doc.invoices || [], function(i, row) {
|
$.each(me.frm.doc.invoices || [], function(i, row) {
|
||||||
if (row.invoice_number && !inList(invoices, row.invoice_number))
|
if (row.invoice_number && !inList(invoices, row.invoice_number))
|
||||||
invoices.push(row.invoice_number);
|
invoices.push(row.invoice_type + " | " + row.invoice_number);
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.meta.get_docfield("Payment Reconciliation Payment", "invoice_number",
|
frappe.meta.get_docfield("Payment Reconciliation Payment", "invoice_number",
|
||||||
|
@ -130,7 +130,7 @@
|
|||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Column Break",
|
"label": "",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@ -362,7 +362,7 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-02-05 05:11:42.105088",
|
"modified": "2015-09-21 03:41:24.672227",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Reconciliation",
|
"name": "Payment Reconciliation",
|
||||||
|
@ -140,12 +140,16 @@ class PaymentReconciliation(Document):
|
|||||||
ent.outstanding_amount = e.get('outstanding_amount')
|
ent.outstanding_amount = e.get('outstanding_amount')
|
||||||
|
|
||||||
def reconcile(self, args):
|
def reconcile(self, args):
|
||||||
|
for e in self.get('payments'):
|
||||||
|
if " | " in e.invoice_number:
|
||||||
|
e.invoice_type, e.invoice_number = e.invoice_number.split(" | ")
|
||||||
|
|
||||||
self.get_invoice_entries()
|
self.get_invoice_entries()
|
||||||
self.validate_invoice()
|
self.validate_invoice()
|
||||||
dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
|
dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
|
||||||
lst = []
|
lst = []
|
||||||
for e in self.get('payments'):
|
for e in self.get('payments'):
|
||||||
if e.invoice_type and e.invoice_number and e.allocated_amount:
|
if e.invoice_number and e.allocated_amount:
|
||||||
lst.append({
|
lst.append({
|
||||||
'voucher_no' : e.journal_entry,
|
'voucher_no' : e.journal_entry,
|
||||||
'voucher_detail_no' : e.voucher_detail_number,
|
'voucher_detail_no' : e.voucher_detail_number,
|
||||||
|
@ -124,7 +124,7 @@
|
|||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Column Break",
|
"label": "",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@ -135,51 +135,6 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "allocated_amount",
|
|
||||||
"fieldtype": "Currency",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Allocated amount",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"default": "Sales Invoice",
|
|
||||||
"fieldname": "invoice_type",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Invoice Type",
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -202,6 +157,28 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "allocated_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Allocated amount",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -243,27 +220,6 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "col_break2",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Column Break",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
@ -273,7 +229,7 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2014-12-25 16:26:48.345281",
|
"modified": "2015-09-21 03:39:40.320070",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Reconciliation Payment",
|
"name": "Payment Reconciliation Payment",
|
||||||
|
@ -2375,4 +2375,4 @@
|
|||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"title_field": "title"
|
"title_field": "title"
|
||||||
}
|
}
|
@ -504,7 +504,7 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2015-08-19 12:46:32.687299",
|
"modified": "2015-08-28 02:57:08.769473",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Taxes and Charges",
|
"name": "Purchase Taxes and Charges",
|
||||||
|
@ -36,6 +36,11 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
refresh: function(doc, dt, dn) {
|
refresh: function(doc, dt, dn) {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
|
if(cur_frm.msgbox && cur_frm.msgbox.$wrapper.is(":visible")) {
|
||||||
|
// hide new msgbox
|
||||||
|
cur_frm.msgbox.hide();
|
||||||
|
}
|
||||||
|
|
||||||
cur_frm.dashboard.reset();
|
cur_frm.dashboard.reset();
|
||||||
|
|
||||||
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
|
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
|
||||||
@ -146,7 +151,9 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
method: "set_missing_values",
|
method: "set_missing_values",
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(!r.exc) {
|
if(!r.exc) {
|
||||||
cur_frm.pos_print_format = r.message.print_format;
|
if(r.message && r.message.print_format) {
|
||||||
|
cur_frm.pos_print_format = r.message.print_format;
|
||||||
|
}
|
||||||
cur_frm.doc.__missing_values_set = true;
|
cur_frm.doc.__missing_values_set = true;
|
||||||
me.frm.script_manager.trigger("update_stock");
|
me.frm.script_manager.trigger("update_stock");
|
||||||
frappe.model.set_default_values(me.frm.doc);
|
frappe.model.set_default_values(me.frm.doc);
|
||||||
@ -175,7 +182,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
me.apply_pricing_rule();
|
me.apply_pricing_rule();
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
debit_to: function() {
|
debit_to: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
if(this.frm.doc.debit_to) {
|
if(this.frm.doc.debit_to) {
|
||||||
@ -193,7 +200,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
allocated_amount: function() {
|
allocated_amount: function() {
|
||||||
@ -417,9 +424,9 @@ cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if(cur_frm.doc.is_pos) {
|
if(cur_frm.doc.is_pos) {
|
||||||
frappe.msgprint('<a class="btn btn-primary" \
|
cur_frm.msgbox = frappe.msgprint('<a class="btn btn-primary" \
|
||||||
onclick="cur_frm.print_preview.printit(true)" style="margin-right: 5px;">Print</a>\
|
onclick="cur_frm.print_preview.printit(true)" style="margin-right: 5px;">Print</a>\
|
||||||
<a class="btn btn-default" href="#Form/Sales Invoice/New">New</a>');
|
<a class="btn btn-default" href="#Form/Sales Invoice/New Sales Invoice">New</a>');
|
||||||
|
|
||||||
} else if(cint(frappe.boot.notification_settings.sales_invoice)) {
|
} else if(cint(frappe.boot.notification_settings.sales_invoice)) {
|
||||||
cur_frm.email_doc(frappe.boot.notification_settings.sales_invoice_message);
|
cur_frm.email_doc(frappe.boot.notification_settings.sales_invoice_message);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -35,6 +35,15 @@ class SalesInvoice(SellingController):
|
|||||||
'overflow_type': 'billing'
|
'overflow_type': 'billing'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
def set_indicator(self):
|
||||||
|
"""Set indicator for portal"""
|
||||||
|
if self.outstanding_amount > 0:
|
||||||
|
self.indicator_color = "orange"
|
||||||
|
self.indicator_title = _("Unpaid")
|
||||||
|
else:
|
||||||
|
self.indicator_color = "green"
|
||||||
|
self.indicator_title = _("Paid")
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
super(SalesInvoice, self).validate()
|
super(SalesInvoice, self).validate()
|
||||||
self.validate_posting_time()
|
self.validate_posting_time()
|
||||||
@ -90,7 +99,7 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
# this sequence because outstanding may get -ve
|
# this sequence because outstanding may get -ve
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
|
|
||||||
if not self.is_return:
|
if not self.is_return:
|
||||||
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
||||||
self.check_credit_limit()
|
self.check_credit_limit()
|
||||||
@ -161,10 +170,10 @@ class SalesInvoice(SellingController):
|
|||||||
'extra_cond': """ and exists (select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock=1 and is_return=1)"""
|
'extra_cond': """ and exists (select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock=1 and is_return=1)"""
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
def check_credit_limit(self):
|
def check_credit_limit(self):
|
||||||
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||||
|
|
||||||
validate_against_credit_limit = False
|
validate_against_credit_limit = False
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if not (d.sales_order or d.delivery_note):
|
if not (d.sales_order or d.delivery_note):
|
||||||
@ -282,7 +291,7 @@ class SalesInvoice(SellingController):
|
|||||||
reconcile_against_document(lst)
|
reconcile_against_document(lst)
|
||||||
|
|
||||||
def validate_debit_to_acc(self):
|
def validate_debit_to_acc(self):
|
||||||
account = frappe.db.get_value("Account", self.debit_to,
|
account = frappe.db.get_value("Account", self.debit_to,
|
||||||
["account_type", "report_type", "account_currency"], as_dict=True)
|
["account_type", "report_type", "account_currency"], as_dict=True)
|
||||||
|
|
||||||
if account.report_type != "Balance Sheet":
|
if account.report_type != "Balance Sheet":
|
||||||
@ -290,7 +299,7 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
if self.customer and account.account_type != "Receivable":
|
if self.customer and account.account_type != "Receivable":
|
||||||
frappe.throw(_("Debit To account must be a Receivable account"))
|
frappe.throw(_("Debit To account must be a Receivable account"))
|
||||||
|
|
||||||
self.party_account_currency = account.account_currency
|
self.party_account_currency = account.account_currency
|
||||||
|
|
||||||
def validate_fixed_asset_account(self):
|
def validate_fixed_asset_account(self):
|
||||||
@ -437,18 +446,18 @@ class SalesInvoice(SellingController):
|
|||||||
if cint(self.is_pos) == 1:
|
if cint(self.is_pos) == 1:
|
||||||
if flt(self.paid_amount) == 0:
|
if flt(self.paid_amount) == 0:
|
||||||
if self.cash_bank_account:
|
if self.cash_bank_account:
|
||||||
frappe.db.set(self, 'paid_amount',
|
frappe.db.set(self, 'paid_amount',
|
||||||
flt(flt(self.grand_total) - flt(self.write_off_amount), self.precision("paid_amount")))
|
flt(flt(self.grand_total) - flt(self.write_off_amount), self.precision("paid_amount")))
|
||||||
else:
|
else:
|
||||||
# show message that the amount is not paid
|
# show message that the amount is not paid
|
||||||
frappe.db.set(self,'paid_amount',0)
|
frappe.db.set(self,'paid_amount',0)
|
||||||
frappe.msgprint(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
|
frappe.msgprint(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
|
||||||
else:
|
else:
|
||||||
frappe.db.set(self,'paid_amount',0)
|
frappe.db.set(self,'paid_amount',0)
|
||||||
|
|
||||||
frappe.db.set(self, 'base_paid_amount',
|
frappe.db.set(self, 'base_paid_amount',
|
||||||
flt(self.paid_amount*self.conversion_rate, self.precision("base_paid_amount")))
|
flt(self.paid_amount*self.conversion_rate, self.precision("base_paid_amount")))
|
||||||
|
|
||||||
def check_prev_docstatus(self):
|
def check_prev_docstatus(self):
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if d.sales_order and frappe.db.get_value("Sales Order", d.sales_order, "docstatus") != 1:
|
if d.sales_order and frappe.db.get_value("Sales Order", d.sales_order, "docstatus") != 1:
|
||||||
@ -487,7 +496,7 @@ class SalesInvoice(SellingController):
|
|||||||
from erpnext.accounts.general_ledger import merge_similar_entries
|
from erpnext.accounts.general_ledger import merge_similar_entries
|
||||||
|
|
||||||
gl_entries = []
|
gl_entries = []
|
||||||
|
|
||||||
self.make_customer_gl_entry(gl_entries)
|
self.make_customer_gl_entry(gl_entries)
|
||||||
|
|
||||||
self.make_tax_gl_entries(gl_entries)
|
self.make_tax_gl_entries(gl_entries)
|
||||||
@ -586,7 +595,7 @@ class SalesInvoice(SellingController):
|
|||||||
# write off entries, applicable if only pos
|
# write off entries, applicable if only pos
|
||||||
if self.write_off_account and self.write_off_amount:
|
if self.write_off_account and self.write_off_amount:
|
||||||
write_off_account_currency = frappe.db.get_value("Account", self.write_off_account, "account_currency")
|
write_off_account_currency = frappe.db.get_value("Account", self.write_off_account, "account_currency")
|
||||||
|
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": self.debit_to,
|
"account": self.debit_to,
|
||||||
|
@ -456,7 +456,7 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2015-08-19 12:46:33.165519",
|
"modified": "2015-08-28 02:57:00.766305",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Taxes and Charges",
|
"name": "Sales Taxes and Charges",
|
||||||
|
@ -5,6 +5,3 @@ cur_frm.cscript.tax_table = "Sales Taxes and Charges";
|
|||||||
|
|
||||||
{% include "public/js/controllers/accounts.js" %}
|
{% include "public/js/controllers/accounts.js" %}
|
||||||
|
|
||||||
frappe.ui.form.on("Sales Taxes and Charges Template", "onload", function(frm) {
|
|
||||||
erpnext.add_applicable_territory();
|
|
||||||
});
|
|
||||||
|
@ -164,29 +164,6 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"description": "Specify a list of Territories, for which, this Taxes Master is valid",
|
|
||||||
"fieldname": "territories",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Valid for Territories",
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Applicable Territory",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
@ -198,7 +175,7 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-09-11 12:19:46.488710",
|
"modified": "2015-09-17 07:09:28.797959",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Taxes and Charges Template",
|
"name": "Sales Taxes and Charges Template",
|
||||||
@ -206,7 +183,7 @@
|
|||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
"apply_user_permissions": 1,
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"delete": 0,
|
"delete": 0,
|
||||||
|
@ -5,7 +5,6 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from erpnext.controllers.accounts_controller import validate_taxes_and_charges, validate_inclusive_tax
|
from erpnext.controllers.accounts_controller import validate_taxes_and_charges, validate_inclusive_tax
|
||||||
from frappe.utils.nestedset import get_root_of
|
|
||||||
|
|
||||||
class SalesTaxesandChargesTemplate(Document):
|
class SalesTaxesandChargesTemplate(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
@ -20,10 +19,6 @@ def valdiate_taxes_and_charges_template(doc):
|
|||||||
where ifnull(is_default,0) = 1 and name != %s and company = %s""".format(doc.doctype),
|
where ifnull(is_default,0) = 1 and name != %s and company = %s""".format(doc.doctype),
|
||||||
(doc.name, doc.company))
|
(doc.name, doc.company))
|
||||||
|
|
||||||
if doc.meta.get_field("territories"):
|
|
||||||
if not doc.territories:
|
|
||||||
doc.append("territories", {"territory": get_root_of("Territory") })
|
|
||||||
|
|
||||||
for tax in doc.get("taxes"):
|
for tax in doc.get("taxes"):
|
||||||
validate_taxes_and_charges(tax)
|
validate_taxes_and_charges(tax)
|
||||||
validate_inclusive_tax(tax, doc)
|
validate_inclusive_tax(tax, doc)
|
||||||
|
@ -20,19 +20,7 @@
|
|||||||
"rate": 6.36
|
"rate": 6.36
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"title": "_Test Sales Taxes and Charges Template",
|
"title": "_Test Sales Taxes and Charges Template"
|
||||||
"territories": [
|
|
||||||
{
|
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"parentfield": "territories",
|
|
||||||
"territory": "All Territories"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"parentfield": "territories",
|
|
||||||
"territory": "_Test Territory Rest Of The World"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
@ -115,14 +103,7 @@
|
|||||||
"row_id": 7
|
"row_id": 7
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"title": "_Test India Tax Master",
|
"title": "_Test India Tax Master"
|
||||||
"territories": [
|
|
||||||
{
|
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"parentfield": "territories",
|
|
||||||
"territory": "_Test Territory India"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
@ -145,13 +126,76 @@
|
|||||||
"rate": 4
|
"rate": 4
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"title": "_Test Sales Taxes and Charges Template - Rest of the World",
|
"title": "_Test Sales Taxes and Charges Template - Rest of the World"
|
||||||
"territories": [
|
},
|
||||||
|
{
|
||||||
|
"company": "_Test Company",
|
||||||
|
"doctype": "Sales Taxes and Charges Template",
|
||||||
|
"taxes": [
|
||||||
{
|
{
|
||||||
"doctype": "Applicable Territory",
|
"account_head": "_Test Account VAT - _TC",
|
||||||
"parentfield": "territories",
|
"charge_type": "On Net Total",
|
||||||
"territory": "_Test Territory Rest Of The World"
|
"description": "VAT",
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "taxes",
|
||||||
|
"rate": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"description": "Service Tax",
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "taxes",
|
||||||
|
"rate": 4
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"title": "_Test Sales Taxes and Charges Template 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"company": "_Test Company",
|
||||||
|
"doctype": "Sales Taxes and Charges Template",
|
||||||
|
"taxes": [
|
||||||
|
{
|
||||||
|
"account_head": "_Test Account VAT - _TC",
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"description": "VAT",
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "taxes",
|
||||||
|
"rate": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"description": "Service Tax",
|
||||||
|
"doctype": "Sales Taxes and Charges",
|
||||||
|
"parentfield": "taxes",
|
||||||
|
"rate": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "_Test Sales Taxes and Charges Template 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype" : "Sales Taxes and Charges Template",
|
||||||
|
"title": "_Test Tax 1",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"taxes":[{
|
||||||
|
"charge_type": "Actual",
|
||||||
|
"account_head": "Sales Expenses - _TC",
|
||||||
|
"cost_center": "Main - _TC",
|
||||||
|
"description": "Test Shopping cart taxes with Tax Rule",
|
||||||
|
"tax_amount": 1000
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype" : "Sales Taxes and Charges Template",
|
||||||
|
"title": "_Test Tax 2",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"taxes":[{
|
||||||
|
"charge_type": "Actual",
|
||||||
|
"account_head": "Sales Expenses - _TC",
|
||||||
|
"cost_center": "Main - _TC",
|
||||||
|
"description": "Test Shopping cart taxes with Tax Rule",
|
||||||
|
"tax_amount": 200
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
$.extend(cur_frm.cscript, {
|
|
||||||
onload: function() {
|
|
||||||
erpnext.add_applicable_territory();
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,388 +1,397 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"autoname": "field:label",
|
"autoname": "field:label",
|
||||||
"creation": "2013-06-25 11:48:03",
|
"creation": "2013-06-25 11:48:03",
|
||||||
"custom": 0,
|
"custom": 0,
|
||||||
"description": "Specify conditions to calculate shipping amount",
|
"description": "Specify conditions to calculate shipping amount",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"description": "example: Next Day Shipping",
|
"description": "example: Next Day Shipping",
|
||||||
"fieldname": "label",
|
"fieldname": "label",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Shipping Rule Label",
|
"label": "Shipping Rule Label",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "column_break_2",
|
"fieldname": "disabled",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"no_copy": 0,
|
"label": "Disabled",
|
||||||
"permlevel": 0,
|
"no_copy": 0,
|
||||||
"print_hide": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"precision": "",
|
||||||
"report_hide": 0,
|
"print_hide": 0,
|
||||||
"reqd": 0,
|
"read_only": 0,
|
||||||
"search_index": 0,
|
"report_hide": 0,
|
||||||
"set_only_once": 0,
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"default": "Net Total",
|
"default": "Net Total",
|
||||||
"fieldname": "calculate_based_on",
|
"fieldname": "calculate_based_on",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Calculate Based On",
|
"label": "Calculate Based On",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Net Total\nNet Weight",
|
"options": "Net Total\nNet Weight",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "rule_conditions_section",
|
"depends_on": "eval:!doc.disabled",
|
||||||
"fieldtype": "Section Break",
|
"fieldname": "rule_conditions_section",
|
||||||
"hidden": 0,
|
"fieldtype": "Section Break",
|
||||||
"ignore_user_permissions": 0,
|
"hidden": 0,
|
||||||
"in_filter": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_list_view": 0,
|
"in_filter": 0,
|
||||||
"label": "Shipping Rule Conditions",
|
"in_list_view": 0,
|
||||||
"no_copy": 0,
|
"label": "Shipping Rule Conditions",
|
||||||
"permlevel": 0,
|
"no_copy": 0,
|
||||||
"print_hide": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"print_hide": 0,
|
||||||
"report_hide": 0,
|
"read_only": 0,
|
||||||
"reqd": 0,
|
"report_hide": 0,
|
||||||
"search_index": 0,
|
"reqd": 0,
|
||||||
"set_only_once": 0,
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "conditions",
|
"fieldname": "conditions",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Shipping Rule Conditions",
|
"label": "Shipping Rule Conditions",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Shipping Rule Condition",
|
"options": "Shipping Rule Condition",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "section_break_6",
|
"depends_on": "eval:!doc.disabled",
|
||||||
"fieldtype": "Section Break",
|
"fieldname": "section_break_6",
|
||||||
"hidden": 0,
|
"fieldtype": "Section Break",
|
||||||
"ignore_user_permissions": 0,
|
"hidden": 0,
|
||||||
"in_filter": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_list_view": 0,
|
"in_filter": 0,
|
||||||
"no_copy": 0,
|
"in_list_view": 0,
|
||||||
"permlevel": 0,
|
"label": "Valid for Countries",
|
||||||
"print_hide": 0,
|
"no_copy": 0,
|
||||||
"read_only": 0,
|
"permlevel": 0,
|
||||||
"report_hide": 0,
|
"print_hide": 0,
|
||||||
"reqd": 0,
|
"read_only": 0,
|
||||||
"search_index": 0,
|
"report_hide": 0,
|
||||||
"set_only_once": 0,
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"description": "Specify a list of Territories, for which, this Shipping Rule is valid",
|
"fieldname": "worldwide_shipping",
|
||||||
"fieldname": "territories",
|
"fieldtype": "Check",
|
||||||
"fieldtype": "Table",
|
"hidden": 0,
|
||||||
"hidden": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_user_permissions": 0,
|
"in_filter": 0,
|
||||||
"in_filter": 0,
|
"in_list_view": 0,
|
||||||
"in_list_view": 0,
|
"label": "Worldwide Shipping",
|
||||||
"label": "Valid For Territories",
|
"no_copy": 0,
|
||||||
"no_copy": 0,
|
"permlevel": 0,
|
||||||
"options": "Applicable Territory",
|
"precision": "",
|
||||||
"permlevel": 0,
|
"print_hide": 0,
|
||||||
"print_hide": 0,
|
"read_only": 0,
|
||||||
"read_only": 0,
|
"report_hide": 0,
|
||||||
"report_hide": 0,
|
"reqd": 0,
|
||||||
"reqd": 1,
|
"search_index": 0,
|
||||||
"search_index": 0,
|
"set_only_once": 0,
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "column_break_8",
|
"depends_on": "eval:!doc.worldwide_shipping",
|
||||||
"fieldtype": "Column Break",
|
"fieldname": "countries",
|
||||||
"hidden": 0,
|
"fieldtype": "Table",
|
||||||
"ignore_user_permissions": 0,
|
"hidden": 0,
|
||||||
"in_filter": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_list_view": 0,
|
"in_filter": 0,
|
||||||
"no_copy": 0,
|
"in_list_view": 0,
|
||||||
"permlevel": 0,
|
"label": "Valid for Countries",
|
||||||
"print_hide": 0,
|
"no_copy": 0,
|
||||||
"read_only": 0,
|
"options": "Shipping Rule Country",
|
||||||
"report_hide": 0,
|
"permlevel": 0,
|
||||||
"reqd": 0,
|
"precision": "",
|
||||||
"search_index": 0,
|
"print_hide": 0,
|
||||||
"set_only_once": 0,
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "company",
|
"depends_on": "eval:!doc.disabled",
|
||||||
"fieldtype": "Link",
|
"fieldname": "section_break_10",
|
||||||
"hidden": 0,
|
"fieldtype": "Section Break",
|
||||||
"ignore_user_permissions": 0,
|
"hidden": 0,
|
||||||
"in_filter": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_list_view": 0,
|
"in_filter": 0,
|
||||||
"label": "Company",
|
"in_list_view": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Company",
|
"permlevel": 0,
|
||||||
"permlevel": 0,
|
"print_hide": 0,
|
||||||
"print_hide": 0,
|
"read_only": 0,
|
||||||
"read_only": 0,
|
"report_hide": 0,
|
||||||
"report_hide": 0,
|
"reqd": 0,
|
||||||
"reqd": 1,
|
"search_index": 0,
|
||||||
"search_index": 0,
|
"set_only_once": 0,
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "section_break_10",
|
"fieldname": "company",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"no_copy": 0,
|
"label": "Company",
|
||||||
"permlevel": 0,
|
"no_copy": 0,
|
||||||
"print_hide": 0,
|
"options": "Company",
|
||||||
"read_only": 0,
|
"permlevel": 0,
|
||||||
"report_hide": 0,
|
"print_hide": 0,
|
||||||
"reqd": 0,
|
"read_only": 0,
|
||||||
"search_index": 0,
|
"report_hide": 0,
|
||||||
"set_only_once": 0,
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "account",
|
"fieldname": "column_break_12",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Shipping Account",
|
"no_copy": 0,
|
||||||
"no_copy": 0,
|
"permlevel": 0,
|
||||||
"options": "Account",
|
"print_hide": 0,
|
||||||
"permlevel": 0,
|
"read_only": 0,
|
||||||
"print_hide": 0,
|
"report_hide": 0,
|
||||||
"read_only": 0,
|
"reqd": 0,
|
||||||
"report_hide": 0,
|
"search_index": 0,
|
||||||
"reqd": 1,
|
"set_only_once": 0,
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "column_break_12",
|
"fieldname": "account",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"no_copy": 0,
|
"label": "Shipping Account",
|
||||||
"permlevel": 0,
|
"no_copy": 0,
|
||||||
"print_hide": 0,
|
"options": "Account",
|
||||||
"read_only": 0,
|
"permlevel": 0,
|
||||||
"report_hide": 0,
|
"print_hide": 0,
|
||||||
"reqd": 0,
|
"read_only": 0,
|
||||||
"search_index": 0,
|
"report_hide": 0,
|
||||||
"set_only_once": 0,
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "cost_center",
|
"fieldname": "cost_center",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Cost Center",
|
"label": "Cost Center",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Cost Center",
|
"options": "Cost Center",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
"hide_toolbar": 0,
|
"hide_toolbar": 0,
|
||||||
"icon": "icon-truck",
|
"icon": "icon-truck",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"in_dialog": 0,
|
"in_dialog": 0,
|
||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-09-07 15:51:26",
|
"modified": "2015-09-22 08:30:57.226342",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Shipping Rule",
|
"name": "Shipping Rule",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
"apply_user_permissions": 1,
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"delete": 0,
|
"delete": 0,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 0,
|
"export": 0,
|
||||||
"if_owner": 0,
|
"if_owner": 0,
|
||||||
"import": 0,
|
"import": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Accounts User",
|
"role": "Accounts User",
|
||||||
"set_user_permissions": 0,
|
"set_user_permissions": 0,
|
||||||
"share": 0,
|
"share": 0,
|
||||||
"submit": 0,
|
"submit": 0,
|
||||||
"write": 0
|
"write": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
"apply_user_permissions": 1,
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"delete": 0,
|
"delete": 0,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 0,
|
"export": 0,
|
||||||
"if_owner": 0,
|
"if_owner": 0,
|
||||||
"import": 0,
|
"import": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Sales User",
|
"role": "Sales User",
|
||||||
"set_user_permissions": 0,
|
"set_user_permissions": 0,
|
||||||
"share": 0,
|
"share": 0,
|
||||||
"submit": 0,
|
"submit": 0,
|
||||||
"write": 0
|
"write": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
"apply_user_permissions": 0,
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 0,
|
"export": 0,
|
||||||
"if_owner": 0,
|
"if_owner": 0,
|
||||||
"import": 0,
|
"import": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Accounts Manager",
|
"role": "Accounts Manager",
|
||||||
"set_user_permissions": 0,
|
"set_user_permissions": 0,
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
"submit": 0,
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
"apply_user_permissions": 0,
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 0,
|
"export": 0,
|
||||||
"if_owner": 0,
|
"if_owner": 0,
|
||||||
"import": 0,
|
"import": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Sales Master Manager",
|
"role": "Sales Master Manager",
|
||||||
"set_user_permissions": 0,
|
"set_user_permissions": 0,
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
"submit": 0,
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0
|
"read_only_onload": 0
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,12 @@ class ShippingRule(Document):
|
|||||||
self.sort_shipping_rule_conditions()
|
self.sort_shipping_rule_conditions()
|
||||||
self.validate_overlapping_shipping_rule_conditions()
|
self.validate_overlapping_shipping_rule_conditions()
|
||||||
|
|
||||||
|
if self.worldwide_shipping:
|
||||||
|
self.countries = []
|
||||||
|
|
||||||
|
elif not len([d.country for d in self.countries if d.country]):
|
||||||
|
frappe.throw(_("Please specify a country for this Shipping Rule or check Worldwide Shipping"))
|
||||||
|
|
||||||
def validate_from_to_values(self):
|
def validate_from_to_values(self):
|
||||||
zero_to_values = []
|
zero_to_values = []
|
||||||
|
|
||||||
|
@ -1,116 +1,100 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"account": "_Test Account Shipping Charges - _TC",
|
"account": "_Test Account Shipping Charges - _TC",
|
||||||
"calculate_based_on": "Net Total",
|
"calculate_based_on": "Net Total",
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"doctype": "Shipping Rule",
|
"doctype": "Shipping Rule",
|
||||||
"label": "_Test Shipping Rule",
|
"label": "_Test Shipping Rule",
|
||||||
"name": "_Test Shipping Rule",
|
"name": "_Test Shipping Rule",
|
||||||
"conditions": [
|
"conditions": [
|
||||||
{
|
{
|
||||||
"doctype": "Shipping Rule Condition",
|
"doctype": "Shipping Rule Condition",
|
||||||
"from_value": 0,
|
"from_value": 0,
|
||||||
"parentfield": "conditions",
|
"parentfield": "conditions",
|
||||||
"shipping_amount": 50.0,
|
"shipping_amount": 50.0,
|
||||||
"to_value": 100
|
"to_value": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Shipping Rule Condition",
|
"doctype": "Shipping Rule Condition",
|
||||||
"from_value": 101,
|
"from_value": 101,
|
||||||
"parentfield": "conditions",
|
"parentfield": "conditions",
|
||||||
"shipping_amount": 100.0,
|
"shipping_amount": 100.0,
|
||||||
"to_value": 200
|
"to_value": 200
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Shipping Rule Condition",
|
"doctype": "Shipping Rule Condition",
|
||||||
"from_value": 201,
|
"from_value": 201,
|
||||||
"parentfield": "conditions",
|
"parentfield": "conditions",
|
||||||
"shipping_amount": 0.0
|
"shipping_amount": 0.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"territories": [
|
"worldwide_shipping": 1
|
||||||
{
|
},
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"parentfield": "territories",
|
|
||||||
"territory": "_Test Territory"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"account": "_Test Account Shipping Charges - _TC",
|
"account": "_Test Account Shipping Charges - _TC",
|
||||||
"calculate_based_on": "Net Total",
|
"calculate_based_on": "Net Total",
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"doctype": "Shipping Rule",
|
"doctype": "Shipping Rule",
|
||||||
"label": "_Test Shipping Rule - India",
|
"label": "_Test Shipping Rule - India",
|
||||||
"name": "_Test Shipping Rule - India",
|
"name": "_Test Shipping Rule - India",
|
||||||
"conditions": [
|
"conditions": [
|
||||||
{
|
{
|
||||||
"doctype": "Shipping Rule Condition",
|
"doctype": "Shipping Rule Condition",
|
||||||
"from_value": 0,
|
"from_value": 0,
|
||||||
"parentfield": "conditions",
|
"parentfield": "conditions",
|
||||||
"shipping_amount": 50.0,
|
"shipping_amount": 50.0,
|
||||||
"to_value": 100
|
"to_value": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Shipping Rule Condition",
|
"doctype": "Shipping Rule Condition",
|
||||||
"from_value": 101,
|
"from_value": 101,
|
||||||
"parentfield": "conditions",
|
"parentfield": "conditions",
|
||||||
"shipping_amount": 100.0,
|
"shipping_amount": 100.0,
|
||||||
"to_value": 200
|
"to_value": 200
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Shipping Rule Condition",
|
"doctype": "Shipping Rule Condition",
|
||||||
"from_value": 201,
|
"from_value": 201,
|
||||||
"parentfield": "conditions",
|
"parentfield": "conditions",
|
||||||
"shipping_amount": 0.0
|
"shipping_amount": 0.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"territories": [
|
"countries": [
|
||||||
{
|
{"country": "India"}
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"parentfield": "territories",
|
|
||||||
"territory": "_Test Territory India"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account": "_Test Account Shipping Charges - _TC",
|
"account": "_Test Account Shipping Charges - _TC",
|
||||||
"calculate_based_on": "Net Total",
|
"calculate_based_on": "Net Total",
|
||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"doctype": "Shipping Rule",
|
"doctype": "Shipping Rule",
|
||||||
"label": "_Test Shipping Rule - Rest of the World",
|
"label": "_Test Shipping Rule - Rest of the World",
|
||||||
"name": "_Test Shipping Rule - Rest of the World",
|
"name": "_Test Shipping Rule - Rest of the World",
|
||||||
"conditions": [
|
"conditions": [
|
||||||
{
|
{
|
||||||
"doctype": "Shipping Rule Condition",
|
"doctype": "Shipping Rule Condition",
|
||||||
"from_value": 0,
|
"from_value": 0,
|
||||||
"parentfield": "conditions",
|
"parentfield": "conditions",
|
||||||
"shipping_amount": 500.0,
|
"shipping_amount": 500.0,
|
||||||
"to_value": 1000
|
"to_value": 1000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Shipping Rule Condition",
|
"doctype": "Shipping Rule Condition",
|
||||||
"from_value": 1001,
|
"from_value": 1001,
|
||||||
"parentfield": "conditions",
|
"parentfield": "conditions",
|
||||||
"shipping_amount": 1000.0,
|
"shipping_amount": 1000.0,
|
||||||
"to_value": 2000
|
"to_value": 2000
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Shipping Rule Condition",
|
"doctype": "Shipping Rule Condition",
|
||||||
"from_value": 2001,
|
"from_value": 2001,
|
||||||
"parentfield": "conditions",
|
"parentfield": "conditions",
|
||||||
"shipping_amount": 1500.0
|
"shipping_amount": 1500.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"territories": [
|
"worldwide_shipping": 1
|
||||||
{
|
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"parentfield": "territories",
|
|
||||||
"territory": "_Test Territory Rest Of The World"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2,25 +2,27 @@
|
|||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"creation": "2013-06-20 16:57:03",
|
"creation": "2015-09-17 06:43:22.767534",
|
||||||
"custom": 0,
|
"custom": 0,
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
|
"document_type": "Other",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "sales_taxes_and_charges_master",
|
"fieldname": "country",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Tax Master",
|
"label": "Country",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Sales Taxes and Charges Template",
|
"options": "Country",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
@ -32,18 +34,20 @@
|
|||||||
],
|
],
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
"hide_toolbar": 0,
|
"hide_toolbar": 0,
|
||||||
"idx": 1,
|
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"in_dialog": 0,
|
"in_dialog": 0,
|
||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2013-12-20 19:30:47",
|
"modified": "2015-09-17 06:43:22.767534",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Shopping Cart",
|
"module": "Accounts",
|
||||||
"name": "Shopping Cart Taxes and Charges Master",
|
"name": "Shipping Rule Country",
|
||||||
|
"name_case": "",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0
|
"read_only_onload": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC"
|
||||||
}
|
}
|
@ -1,12 +1,10 @@
|
|||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
# -*- coding: utf-8 -*-
|
||||||
# MIT License. See license.txt
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class ApplicableTerritory(Document):
|
class ShippingRuleCountry(Document):
|
||||||
pass
|
pass
|
60
erpnext/accounts/doctype/tax_rule/tax_rule.js
Normal file
60
erpnext/accounts/doctype/tax_rule/tax_rule.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
cur_frm.add_fetch("customer", "customer_group", "customer_group" );
|
||||||
|
cur_frm.add_fetch("supplier", "supplier_type", "supplier_type" );
|
||||||
|
|
||||||
|
cur_frm.toggle_reqd("sales_tax_template", cur_frm.doc.tax_type=="Sales");
|
||||||
|
cur_frm.toggle_reqd("purchase_tax_template", cur_frm.doc.tax_type=="Purchase");
|
||||||
|
|
||||||
|
|
||||||
|
frappe.ui.form.on("Tax Rule", "onload", function(frm) {
|
||||||
|
if(frm.doc.__islocal){
|
||||||
|
frm.set_value("use_for_shopping_cart", 1);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
frappe.ui.form.on("Tax Rule", "use_for_shopping_cart", function(frm) {
|
||||||
|
if(!frm.doc.use_for_shopping_cart && (frappe.get_list("Tax Rule", {"use_for_shopping_cart":1}).length == 0)){
|
||||||
|
frappe.model.get_value("Shopping Cart Settings", "Shopping Cart Settings", "enabled", function(docfield) {
|
||||||
|
if(docfield.enabled){
|
||||||
|
frm.set_value("use_for_shopping_cart", 1);
|
||||||
|
frappe.throw(__("Shopping Cart is enabled"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
frappe.ui.form.on("Tax Rule", "customer", function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
|
||||||
|
args: {
|
||||||
|
"party": frm.doc.customer,
|
||||||
|
"party_type": "customer"
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if(!r.exc) {
|
||||||
|
$.each(r.message, function(k, v) {
|
||||||
|
frm.set_value(k, v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
frappe.ui.form.on("Tax Rule", "supplier", function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
|
||||||
|
args: {
|
||||||
|
"party": frm.doc.supplier,
|
||||||
|
"party_type": "supplier"
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if(!r.exc) {
|
||||||
|
$.each(r.message, function(k, v) {
|
||||||
|
frm.set_value(k, v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
615
erpnext/accounts/doctype/tax_rule/tax_rule.json
Normal file
615
erpnext/accounts/doctype/tax_rule/tax_rule.json
Normal file
@ -0,0 +1,615 @@
|
|||||||
|
{
|
||||||
|
"allow_copy": 0,
|
||||||
|
"allow_import": 1,
|
||||||
|
"allow_rename": 0,
|
||||||
|
"autoname": "TR.####",
|
||||||
|
"creation": "2015-08-07 02:33:52.670866",
|
||||||
|
"custom": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "Setup",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"default": "Sales",
|
||||||
|
"fieldname": "tax_type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Tax Type",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Sales\nPurchase",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "use_for_shopping_cart",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Use for Shopping Cart",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "column_break_1",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"depends_on": "eval:doc.tax_type==\"Sales\"",
|
||||||
|
"fieldname": "sales_tax_template",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Sales Tax Template",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Sales Taxes and Charges Template",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"depends_on": "eval:doc.tax_type==\"Purchase\"",
|
||||||
|
"fieldname": "purchase_tax_template",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Purchase Tax Template",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Purchase Taxes and Charges Template",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "filters",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Filters",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"depends_on": "eval:doc.tax_type==\"Sales\"",
|
||||||
|
"fieldname": "customer",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Customer",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Customer",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"depends_on": "eval:doc.tax_type==\"Purchase\"",
|
||||||
|
"fieldname": "supplier",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Supplier",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Supplier",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "billing_city",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Billing City",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "billing_state",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Billing State",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "billing_country",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Billing Country",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Country",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "column_break_2",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"depends_on": "eval:doc.tax_type==\"Sales\"",
|
||||||
|
"fieldname": "customer_group",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Customer Group",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Customer Group",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"depends_on": "eval:doc.tax_type==\"Purchase\"",
|
||||||
|
"fieldname": "supplier_type",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Supplier Type",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Supplier Type",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "shipping_city",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Shipping City",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "shipping_state",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Shipping State",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "shipping_country",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Shipping Country",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Country",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "section_break_4",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Validity",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "from_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "From Date",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "column_break_7",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "to_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "To Date",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "section_break_6",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"default": "1",
|
||||||
|
"fieldname": "priority",
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Priority",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "column_break_20",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"fieldname": "company",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Company",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Company",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hide_heading": 0,
|
||||||
|
"hide_toolbar": 0,
|
||||||
|
"in_create": 0,
|
||||||
|
"in_dialog": 0,
|
||||||
|
"is_submittable": 0,
|
||||||
|
"issingle": 0,
|
||||||
|
"istable": 0,
|
||||||
|
"modified": "2015-09-15 12:29:34.435839",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Tax Rule",
|
||||||
|
"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": "Administrator",
|
||||||
|
"set_user_permissions": 0,
|
||||||
|
"share": 1,
|
||||||
|
"submit": 0,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"read_only": 0,
|
||||||
|
"read_only_onload": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC"
|
||||||
|
}
|
140
erpnext/accounts/doctype/tax_rule/tax_rule.py
Normal file
140
erpnext/accounts/doctype/tax_rule/tax_rule.py
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.model.document import Document
|
||||||
|
from frappe.utils import cstr
|
||||||
|
|
||||||
|
class IncorrectCustomerGroup(frappe.ValidationError): pass
|
||||||
|
class IncorrectSupplierType(frappe.ValidationError): pass
|
||||||
|
class ConflictingTaxRule(frappe.ValidationError): pass
|
||||||
|
|
||||||
|
class TaxRule(Document):
|
||||||
|
def __setup__(self):
|
||||||
|
self.flags.ignore_these_exceptions_in_test = [ConflictingTaxRule]
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
self.validate_tax_template()
|
||||||
|
self.validate_customer_group()
|
||||||
|
self.validate_supplier_type()
|
||||||
|
self.validate_date()
|
||||||
|
self.validate_filters()
|
||||||
|
|
||||||
|
def validate_tax_template(self):
|
||||||
|
if self.tax_type== "Sales":
|
||||||
|
self.purchase_tax_template = self.supplier = self.supplier_type= None
|
||||||
|
else:
|
||||||
|
self.sales_tax_template= self.customer = self.customer_group= None
|
||||||
|
|
||||||
|
if not (self.sales_tax_template or self.purchase_tax_template):
|
||||||
|
frappe.throw(_("Tax Template is mandatory."))
|
||||||
|
|
||||||
|
def validate_customer_group(self):
|
||||||
|
if self.customer and self.customer_group:
|
||||||
|
if not frappe.db.get_value("Customer", self.customer, "customer_group") == self.customer_group:
|
||||||
|
frappe.throw(_("Customer {0} does not belong to customer group {1}"). \
|
||||||
|
format(self.customer, self.customer_group), IncorrectCustomerGroup)
|
||||||
|
|
||||||
|
def validate_supplier_type(self):
|
||||||
|
if self.supplier and self.supplier_type:
|
||||||
|
if not frappe.db.get_value("Supplier", self.supplier, "supplier_type") == self.supplier_type:
|
||||||
|
frappe.throw(_("Supplier {0} does not belong to Supplier Type {1}"). \
|
||||||
|
format(self.supplier, self.supplier_type), IncorrectSupplierType)
|
||||||
|
|
||||||
|
def validate_date(self):
|
||||||
|
if self.from_date and self.to_date and self.from_date > self.to_date:
|
||||||
|
frappe.throw(_("From Date cannot be greater than To Date"))
|
||||||
|
|
||||||
|
def validate_filters(self):
|
||||||
|
filters = {
|
||||||
|
"tax_type": self.tax_type,
|
||||||
|
"customer": self.customer,
|
||||||
|
"customer_group": self.customer_group,
|
||||||
|
"supplier": self.supplier,
|
||||||
|
"supplier_type": self.supplier_type,
|
||||||
|
"billing_city": self.billing_city,
|
||||||
|
"billing_state": self.billing_state,
|
||||||
|
"billing_country": self.billing_country,
|
||||||
|
"shipping_city": self.shipping_city,
|
||||||
|
"shipping_state": self.shipping_state,
|
||||||
|
"shipping_country": self.shipping_country,
|
||||||
|
"company": self.company
|
||||||
|
}
|
||||||
|
|
||||||
|
conds=""
|
||||||
|
for d in filters:
|
||||||
|
if conds:
|
||||||
|
conds += " and "
|
||||||
|
conds += """ifnull({0}, '') = '{1}'""".format(d, frappe.db.escape(cstr(filters[d])))
|
||||||
|
|
||||||
|
if self.from_date and self.to_date:
|
||||||
|
conds += """ and ((from_date > '{from_date}' and from_date < '{to_date}') or
|
||||||
|
(to_date > '{from_date}' and to_date < '{to_date}') or
|
||||||
|
('{from_date}' > from_date and '{from_date}' < to_date) or
|
||||||
|
('{from_date}' = from_date and '{to_date}' = to_date))""".format(from_date=self.from_date, to_date=self.to_date)
|
||||||
|
|
||||||
|
elif self.from_date and not self.to_date:
|
||||||
|
conds += """ and to_date > '{from_date}'""".format(from_date = self.from_date)
|
||||||
|
|
||||||
|
elif self.to_date and not self.from_date:
|
||||||
|
conds += """ and from_date < '{to_date}'""".format(to_date = self.to_date)
|
||||||
|
|
||||||
|
tax_rule = frappe.db.sql("select name, priority \
|
||||||
|
from `tabTax Rule` where {0} and name != '{1}'".format(conds, self.name), as_dict=1)
|
||||||
|
|
||||||
|
if tax_rule:
|
||||||
|
if tax_rule[0].priority == self.priority:
|
||||||
|
frappe.throw(_("Tax Rule Conflicts with {0}".format(tax_rule[0].name)), ConflictingTaxRule)
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_party_details(party, party_type, args=None):
|
||||||
|
out = {}
|
||||||
|
if args:
|
||||||
|
billing_filters= {"name": args.get("billing_address")}
|
||||||
|
shipping_filters= {"name": args.get("shipping_address")}
|
||||||
|
else:
|
||||||
|
billing_filters= {party_type: party, "is_primary_address": 1}
|
||||||
|
shipping_filters= {party_type:party, "is_shipping_address": 1}
|
||||||
|
|
||||||
|
billing_address= frappe.get_all("Address", fields=["city", "state", "country"], filters= billing_filters)
|
||||||
|
shipping_address= frappe.get_all("Address", fields=["city", "state", "country"], filters= shipping_filters)
|
||||||
|
|
||||||
|
if billing_address:
|
||||||
|
out["billing_city"]= billing_address[0].city
|
||||||
|
out["billing_state"]= billing_address[0].state
|
||||||
|
out["billing_country"]= billing_address[0].country
|
||||||
|
|
||||||
|
if shipping_address:
|
||||||
|
out["shipping_city"]= shipping_address[0].city
|
||||||
|
out["shipping_state"]= shipping_address[0].state
|
||||||
|
out["shipping_country"]= shipping_address[0].country
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
def get_tax_template(posting_date, args):
|
||||||
|
"""Get matching tax rule"""
|
||||||
|
args = frappe._dict(args)
|
||||||
|
conditions = []
|
||||||
|
|
||||||
|
for key, value in args.iteritems():
|
||||||
|
if key in "use_for_shopping_cart":
|
||||||
|
conditions.append("use_for_shopping_cart = {0}".format(1 if value else 0))
|
||||||
|
else:
|
||||||
|
conditions.append("ifnull({0}, '') in ('', '{1}')".format(key, frappe.db.escape(cstr(value))))
|
||||||
|
|
||||||
|
matching = frappe.db.sql("""select * from `tabTax Rule`
|
||||||
|
where {0}""".format(" and ".join(conditions)), as_dict = True)
|
||||||
|
|
||||||
|
if not matching:
|
||||||
|
return None
|
||||||
|
|
||||||
|
for rule in matching:
|
||||||
|
rule.no_of_keys_matched = 0
|
||||||
|
for key in args:
|
||||||
|
if rule.get(key): rule.no_of_keys_matched += 1
|
||||||
|
|
||||||
|
rule = sorted(matching, lambda b, a: cmp(a.no_of_keys_matched, b.no_of_keys_matched) or cmp(a.priority, b.priority))[0]
|
||||||
|
return rule.sales_tax_template or rule.purchase_tax_template
|
28
erpnext/accounts/doctype/tax_rule/test_records.json
Normal file
28
erpnext/accounts/doctype/tax_rule/test_records.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"doctype": "Tax Rule",
|
||||||
|
"tax_type" : "Sales",
|
||||||
|
"sales_tax_template": "_Test Tax 1",
|
||||||
|
"use_for_shopping_cart": 1,
|
||||||
|
"billing_city": "_Test City",
|
||||||
|
"billing_state": "Test State",
|
||||||
|
"billing_country": "India",
|
||||||
|
"shipping_city": "_Test City",
|
||||||
|
"shipping_country": "India",
|
||||||
|
"priority": 1,
|
||||||
|
"company": "_Test Company"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Tax Rule",
|
||||||
|
"tax_type" : "Sales",
|
||||||
|
"sales_tax_template": "_Test Tax 2",
|
||||||
|
"use_for_shopping_cart": 0,
|
||||||
|
"billing_city": "_Test City",
|
||||||
|
"billing_country": "India",
|
||||||
|
"shipping_city": "_Test City",
|
||||||
|
"shipping_state": "Test State",
|
||||||
|
"shipping_country": "India",
|
||||||
|
"priority": 2,
|
||||||
|
"company": "_Test Company"
|
||||||
|
}
|
||||||
|
]
|
141
erpnext/accounts/doctype/tax_rule/test_tax_rule.py
Normal file
141
erpnext/accounts/doctype/tax_rule/test_tax_rule.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
import unittest
|
||||||
|
from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup, IncorrectSupplierType, ConflictingTaxRule, get_tax_template
|
||||||
|
|
||||||
|
test_records = frappe.get_test_records('Tax Rule')
|
||||||
|
|
||||||
|
class TestTaxRule(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
frappe.db.sql("delete from `tabTax Rule` where use_for_shopping_cart <> 1")
|
||||||
|
|
||||||
|
def test_customer_group(self):
|
||||||
|
tax_rule = make_tax_rule(customer= "_Test Customer", customer_group= "_Test Customer Group 1",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template")
|
||||||
|
self.assertRaises(IncorrectCustomerGroup, tax_rule.save)
|
||||||
|
|
||||||
|
def test_supplier_type(self):
|
||||||
|
tax_rule = make_tax_rule(tax_type= "Purchase", supplier= "_Test Supplier", supplier_type= "_Test Supplier Type 1",
|
||||||
|
purchase_tax_template = "_Test Purchase Taxes and Charges Template")
|
||||||
|
self.assertRaises(IncorrectSupplierType, tax_rule.save)
|
||||||
|
|
||||||
|
def test_conflict(self):
|
||||||
|
tax_rule1 = make_tax_rule(customer= "_Test Customer",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
|
||||||
|
tax_rule1.save()
|
||||||
|
|
||||||
|
tax_rule2 = make_tax_rule(customer= "_Test Customer",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
|
||||||
|
|
||||||
|
self.assertRaises(ConflictingTaxRule, tax_rule2.save)
|
||||||
|
|
||||||
|
def test_conflict_with_non_overlapping_dates(self):
|
||||||
|
tax_rule1 = make_tax_rule(customer= "_Test Customer",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01")
|
||||||
|
tax_rule1.save()
|
||||||
|
|
||||||
|
tax_rule2 = make_tax_rule(customer= "_Test Customer",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, to_date = "2013-01-01")
|
||||||
|
|
||||||
|
tax_rule2.save()
|
||||||
|
self.assertTrue(tax_rule2.name)
|
||||||
|
|
||||||
|
def test_conflict_with_overlapping_dates(self):
|
||||||
|
tax_rule1 = make_tax_rule(customer= "_Test Customer",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01", to_date = "2015-01-05")
|
||||||
|
tax_rule1.save()
|
||||||
|
|
||||||
|
tax_rule2 = make_tax_rule(customer= "_Test Customer",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-03", to_date = "2015-01-09")
|
||||||
|
|
||||||
|
self.assertRaises(ConflictingTaxRule, tax_rule2.save)
|
||||||
|
|
||||||
|
def test_tax_template(self):
|
||||||
|
tax_rule = make_tax_rule()
|
||||||
|
self.assertEquals(tax_rule.purchase_tax_template, None)
|
||||||
|
|
||||||
|
|
||||||
|
def test_select_tax_rule_based_on_customer(self):
|
||||||
|
make_tax_rule(customer= "_Test Customer",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||||
|
|
||||||
|
make_tax_rule(customer= "_Test Customer 1",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||||
|
|
||||||
|
make_tax_rule(customer= "_Test Customer 2",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template 2", save=1)
|
||||||
|
|
||||||
|
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer 2"}),
|
||||||
|
"_Test Sales Taxes and Charges Template 2")
|
||||||
|
|
||||||
|
def test_select_tax_rule_based_on_better_match(self):
|
||||||
|
make_tax_rule(customer= "_Test Customer", billing_city = "Test City", billing_state = "Test State",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||||
|
|
||||||
|
make_tax_rule(customer= "_Test Customer", billing_city = "Test City1", billing_state = "Test State",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||||
|
|
||||||
|
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City", "billing_state": "Test State"}),
|
||||||
|
"_Test Sales Taxes and Charges Template")
|
||||||
|
|
||||||
|
def test_select_tax_rule_based_on_state_match(self):
|
||||||
|
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||||
|
|
||||||
|
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State12",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1)
|
||||||
|
|
||||||
|
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "shipping_state": "Test State"}),
|
||||||
|
"_Test Sales Taxes and Charges Template")
|
||||||
|
|
||||||
|
def test_select_tax_rule_based_on_better_priority(self):
|
||||||
|
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", priority=1, save=1)
|
||||||
|
|
||||||
|
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1)
|
||||||
|
|
||||||
|
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City"}),
|
||||||
|
"_Test Sales Taxes and Charges Template 1")
|
||||||
|
|
||||||
|
def test_select_tax_rule_based_cross_matching_keys(self):
|
||||||
|
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||||
|
|
||||||
|
make_tax_rule(customer= "_Test Customer 1", billing_city = "Test City 1",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||||
|
|
||||||
|
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
|
||||||
|
None)
|
||||||
|
|
||||||
|
def test_select_tax_rule_based_cross_partially_keys(self):
|
||||||
|
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||||
|
|
||||||
|
make_tax_rule(billing_city = "Test City 1",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||||
|
|
||||||
|
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
|
||||||
|
"_Test Sales Taxes and Charges Template 1")
|
||||||
|
|
||||||
|
|
||||||
|
def make_tax_rule(**args):
|
||||||
|
args = frappe._dict(args)
|
||||||
|
|
||||||
|
tax_rule = frappe.new_doc("Tax Rule")
|
||||||
|
|
||||||
|
for key, val in args.iteritems():
|
||||||
|
if key != "save":
|
||||||
|
tax_rule.set(key, val)
|
||||||
|
|
||||||
|
tax_rule.company = args.company or "_Test Company"
|
||||||
|
|
||||||
|
if args.save:
|
||||||
|
tax_rule.insert()
|
||||||
|
|
||||||
|
return tax_rule
|
||||||
|
|
@ -20,7 +20,7 @@ def get_party_details(party=None, account=None, party_type="Customer", company=N
|
|||||||
|
|
||||||
if not party:
|
if not party:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
if not frappe.db.exists(party_type, party):
|
if not frappe.db.exists(party_type, party):
|
||||||
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
|
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ def get_party_details(party=None, account=None, party_type="Customer", company=N
|
|||||||
|
|
||||||
def _get_party_details(party=None, account=None, party_type="Customer", company=None,
|
def _get_party_details(party=None, account=None, party_type="Customer", company=None,
|
||||||
posting_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False):
|
posting_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False):
|
||||||
|
|
||||||
out = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, doctype))
|
out = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, doctype))
|
||||||
|
|
||||||
party = out[party_type.lower()]
|
party = out[party_type.lower()]
|
||||||
@ -43,6 +43,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
|
|||||||
set_contact_details(out, party, party_type)
|
set_contact_details(out, party, party_type)
|
||||||
set_other_values(out, party, party_type)
|
set_other_values(out, party, party_type)
|
||||||
set_price_list(out, party, party_type, price_list)
|
set_price_list(out, party, party_type, price_list)
|
||||||
|
out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, out.customer_group, out.supplier_type)
|
||||||
|
|
||||||
if not out.get("currency"):
|
if not out.get("currency"):
|
||||||
out["currency"] = currency
|
out["currency"] = currency
|
||||||
@ -50,9 +51,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
|
|||||||
# sales team
|
# sales team
|
||||||
if party_type=="Customer":
|
if party_type=="Customer":
|
||||||
out["sales_team"] = [{
|
out["sales_team"] = [{
|
||||||
"sales_person": d.sales_person,
|
"sales_person": d.sales_person
|
||||||
"sales_designation": d.sales_designation,
|
|
||||||
"allocated_percentage": d.allocated_percentage
|
|
||||||
} for d in party.get("sales_team")]
|
} for d in party.get("sales_team")]
|
||||||
|
|
||||||
return out
|
return out
|
||||||
@ -99,11 +98,24 @@ def set_other_values(out, party, party_type):
|
|||||||
out[f] = party.get(f)
|
out[f] = party.get(f)
|
||||||
|
|
||||||
# fields prepended with default in Customer doctype
|
# fields prepended with default in Customer doctype
|
||||||
for f in ['currency', 'taxes_and_charges'] \
|
for f in ['currency'] \
|
||||||
+ (['sales_partner', 'commission_rate'] if party_type=="Customer" else []):
|
+ (['sales_partner', 'commission_rate'] if party_type=="Customer" else []):
|
||||||
if party.get("default_" + f):
|
if party.get("default_" + f):
|
||||||
out[f] = party.get("default_" + f)
|
out[f] = party.get("default_" + f)
|
||||||
|
|
||||||
|
def get_default_price_list(party):
|
||||||
|
"""Return default price list for party (Document object)"""
|
||||||
|
if party.default_price_list:
|
||||||
|
return party.default_price_list
|
||||||
|
|
||||||
|
if party.doctype == "Customer":
|
||||||
|
price_list = frappe.db.get_value("Customer Group",
|
||||||
|
party.customer_group, "default_price_list")
|
||||||
|
if price_list:
|
||||||
|
return price_list
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
def set_price_list(out, party, party_type, given_price_list):
|
def set_price_list(out, party, party_type, given_price_list):
|
||||||
# price list
|
# price list
|
||||||
price_list = filter(None, get_user_permissions().get("Price List", []))
|
price_list = filter(None, get_user_permissions().get("Price List", []))
|
||||||
@ -111,11 +123,7 @@ def set_price_list(out, party, party_type, given_price_list):
|
|||||||
price_list = price_list[0] if len(price_list)==1 else None
|
price_list = price_list[0] if len(price_list)==1 else None
|
||||||
|
|
||||||
if not price_list:
|
if not price_list:
|
||||||
price_list = party.default_price_list
|
price_list = get_default_price_list(party)
|
||||||
|
|
||||||
if not price_list and party_type=="Customer":
|
|
||||||
price_list = frappe.db.get_value("Customer Group",
|
|
||||||
party.customer_group, "default_price_list")
|
|
||||||
|
|
||||||
if not price_list:
|
if not price_list:
|
||||||
price_list = given_price_list
|
price_list = given_price_list
|
||||||
@ -144,20 +152,11 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
|
|||||||
"due_date": get_due_date(posting_date, party_type, party, company)
|
"due_date": get_due_date(posting_date, party_type, party, company)
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
|
|
||||||
def validate_accounting_currency(party):
|
def validate_accounting_currency(party):
|
||||||
company_currency = get_company_currency()
|
|
||||||
|
|
||||||
# set party account currency
|
|
||||||
if not party.party_account_currency:
|
|
||||||
if party.default_currency:
|
|
||||||
party.party_account_currency = party.default_currency
|
|
||||||
elif len(set(company_currency.values())) == 1:
|
|
||||||
party.party_account_currency = company_currency.values()[0]
|
|
||||||
|
|
||||||
party_account_currency_in_db = frappe.db.get_value(party.doctype, party.name, "party_account_currency")
|
party_account_currency_in_db = frappe.db.get_value(party.doctype, party.name, "party_account_currency")
|
||||||
if party_account_currency_in_db != party.party_account_currency:
|
if party_account_currency_in_db != party.party_account_currency:
|
||||||
existing_gle = frappe.db.get_value("GL Entry", {"party_type": party.doctype,
|
existing_gle = frappe.db.get_value("GL Entry", {"party_type": party.doctype,
|
||||||
"party": party.name}, ["name", "account_currency"], as_dict=1)
|
"party": party.name}, ["name", "account_currency"], as_dict=1)
|
||||||
if existing_gle:
|
if existing_gle:
|
||||||
if party_account_currency_in_db:
|
if party_account_currency_in_db:
|
||||||
@ -165,8 +164,8 @@ def validate_accounting_currency(party):
|
|||||||
.format(party.doctype), InvalidCurrency)
|
.format(party.doctype), InvalidCurrency)
|
||||||
else:
|
else:
|
||||||
party.party_account_currency = existing_gle.account_currency
|
party.party_account_currency = existing_gle.account_currency
|
||||||
|
|
||||||
|
|
||||||
def validate_party_account(party):
|
def validate_party_account(party):
|
||||||
company_currency = get_company_currency()
|
company_currency = get_company_currency()
|
||||||
if party.party_account_currency:
|
if party.party_account_currency:
|
||||||
@ -174,31 +173,31 @@ def validate_party_account(party):
|
|||||||
for company, currency in company_currency.items():
|
for company, currency in company_currency.items():
|
||||||
if currency != party.party_account_currency:
|
if currency != party.party_account_currency:
|
||||||
companies_with_different_currency.append(company)
|
companies_with_different_currency.append(company)
|
||||||
|
|
||||||
for d in party.get("accounts"):
|
for d in party.get("accounts"):
|
||||||
if d.company in companies_with_different_currency:
|
if d.company in companies_with_different_currency:
|
||||||
companies_with_different_currency.remove(d.company)
|
companies_with_different_currency.remove(d.company)
|
||||||
|
|
||||||
selected_account_currency = frappe.db.get_value("Account", d.account, "account_currency")
|
selected_account_currency = frappe.db.get_value("Account", d.account, "account_currency")
|
||||||
if selected_account_currency != party.party_account_currency:
|
if selected_account_currency != party.party_account_currency:
|
||||||
frappe.throw(_("Account {0} is invalid, account currency must be {1}")
|
frappe.throw(_("Account {0} is invalid, account currency must be {1}")
|
||||||
.format(d.account, selected_account_currency), InvalidAccountCurrency)
|
.format(d.account, selected_account_currency), InvalidAccountCurrency)
|
||||||
|
|
||||||
if companies_with_different_currency:
|
if companies_with_different_currency:
|
||||||
frappe.msgprint(_("Please mention Default {0} Account for the following companies, as accounting currency is different from company's default currency: {1}")
|
frappe.msgprint(_("Please mention Default {0} Account for the following companies, as accounting currency is different from company's default currency: {1}")
|
||||||
.format(
|
.format(
|
||||||
"Receivable" if party.doctype=="Customer" else "Payable",
|
"Receivable" if party.doctype=="Customer" else "Payable",
|
||||||
"\n" + "\n".join(companies_with_different_currency)
|
"\n" + "\n".join(companies_with_different_currency)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_company_currency():
|
def get_company_currency():
|
||||||
company_currency = frappe._dict()
|
company_currency = frappe._dict()
|
||||||
for d in frappe.get_all("Company", fields=["name", "default_currency"]):
|
for d in frappe.get_all("Company", fields=["name", "default_currency"]):
|
||||||
company_currency.setdefault(d.name, d.default_currency)
|
company_currency.setdefault(d.name, d.default_currency)
|
||||||
|
|
||||||
return company_currency
|
return company_currency
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_party_account(company, party, party_type):
|
def get_party_account(company, party, party_type):
|
||||||
"""Returns the account for the given `party`.
|
"""Returns the account for the given `party`.
|
||||||
@ -240,7 +239,7 @@ def get_due_date(posting_date, party_type, party, company):
|
|||||||
credit_days = get_credit_days(party_type, party, company)
|
credit_days = get_credit_days(party_type, party, company)
|
||||||
if credit_days:
|
if credit_days:
|
||||||
due_date = add_days(posting_date, credit_days)
|
due_date = add_days(posting_date, credit_days)
|
||||||
|
|
||||||
return due_date
|
return due_date
|
||||||
|
|
||||||
def get_credit_days(party_type, party, company):
|
def get_credit_days(party_type, party, company):
|
||||||
@ -248,21 +247,21 @@ def get_credit_days(party_type, party, company):
|
|||||||
if party_type == "Customer":
|
if party_type == "Customer":
|
||||||
credit_days_based_on, credit_days, customer_group = \
|
credit_days_based_on, credit_days, customer_group = \
|
||||||
frappe.db.get_value(party_type, party, ["credit_days_based_on", "credit_days", "customer_group"])
|
frappe.db.get_value(party_type, party, ["credit_days_based_on", "credit_days", "customer_group"])
|
||||||
|
|
||||||
if not credit_days_based_on:
|
if not credit_days_based_on:
|
||||||
credit_days_based_on, credit_days = \
|
credit_days_based_on, credit_days = \
|
||||||
frappe.db.get_value("Customer Group", customer_group, ["credit_days_based_on", "credit_days"]) \
|
frappe.db.get_value("Customer Group", customer_group, ["credit_days_based_on", "credit_days"]) \
|
||||||
or frappe.db.get_value("Company", company, ["credit_days_based_on", "credit_days"])
|
or frappe.db.get_value("Company", company, ["credit_days_based_on", "credit_days"])
|
||||||
|
|
||||||
return credit_days_based_on, credit_days
|
return credit_days_based_on, credit_days
|
||||||
else:
|
else:
|
||||||
credit_days, supplier_type = frappe.db.get_value(party_type, party, ["credit_days", "supplier_type"])
|
credit_days, supplier_type = frappe.db.get_value(party_type, party, ["credit_days", "supplier_type"])
|
||||||
if not credit_days:
|
if not credit_days:
|
||||||
credit_days = frappe.db.get_value("Supplier Type", supplier_type, "credit_days") \
|
credit_days = frappe.db.get_value("Supplier Type", supplier_type, "credit_days") \
|
||||||
or frappe.db.get_value("Company", company, "credit_days")
|
or frappe.db.get_value("Company", company, "credit_days")
|
||||||
|
|
||||||
return credit_days
|
return credit_days
|
||||||
|
|
||||||
def validate_due_date(posting_date, due_date, party_type, party, company):
|
def validate_due_date(posting_date, due_date, party_type, party, company):
|
||||||
if getdate(due_date) < getdate(posting_date):
|
if getdate(due_date) < getdate(posting_date):
|
||||||
frappe.throw(_("Due Date cannot be before Posting Date"))
|
frappe.throw(_("Due Date cannot be before Posting Date"))
|
||||||
@ -274,4 +273,31 @@ def validate_due_date(posting_date, due_date, party_type, party, company):
|
|||||||
msgprint(_("Note: Due / Reference Date exceeds allowed customer credit days by {0} day(s)")
|
msgprint(_("Note: Due / Reference Date exceeds allowed customer credit days by {0} day(s)")
|
||||||
.format(date_diff(due_date, default_due_date)))
|
.format(date_diff(due_date, default_due_date)))
|
||||||
else:
|
else:
|
||||||
frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date)))
|
frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date)))
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_type=None,
|
||||||
|
billing_address=None, shipping_address=None, use_for_shopping_cart=None):
|
||||||
|
from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details
|
||||||
|
args = {
|
||||||
|
party_type.lower(): party,
|
||||||
|
"customer_group": customer_group,
|
||||||
|
"supplier_type": supplier_type,
|
||||||
|
"company": company
|
||||||
|
}
|
||||||
|
|
||||||
|
if billing_address or shipping_address:
|
||||||
|
args.update(get_party_details(party, party_type, {"billing_address": billing_address, \
|
||||||
|
"shipping_address": shipping_address }))
|
||||||
|
else:
|
||||||
|
args.update(get_party_details(party, party_type))
|
||||||
|
|
||||||
|
if party_type=="Customer":
|
||||||
|
args.update({"tax_type": "Sales"})
|
||||||
|
else:
|
||||||
|
args.update({"tax_type": "Purchase"})
|
||||||
|
|
||||||
|
if use_for_shopping_cart:
|
||||||
|
args.update({"use_for_shopping_cart": use_for_shopping_cart})
|
||||||
|
|
||||||
|
return get_tax_template(posting_date, args)
|
||||||
|
@ -4,17 +4,17 @@ frappe.listview_settings['Purchase Order'] = {
|
|||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if(doc.status==="Stopped") {
|
if(doc.status==="Stopped") {
|
||||||
return [__("Stopped"), "darkgrey", "status,=,Stopped"];
|
return [__("Stopped"), "darkgrey", "status,=,Stopped"];
|
||||||
} else if(flt(doc.per_received) < 100 && doc.status!=="Stopped") {
|
} else if(flt(doc.per_received, 2) < 100 && doc.status!=="Stopped") {
|
||||||
if(flt(doc.per_billed) < 100) {
|
if(flt(doc.per_billed, 2) < 100) {
|
||||||
return [__("To Receive and Bill"), "orange",
|
return [__("To Receive and Bill"), "orange",
|
||||||
"per_received,<,100|per_billed,<,100|status,!=,Stopped"];
|
"per_received,<,100|per_billed,<,100|status,!=,Stopped"];
|
||||||
} else {
|
} else {
|
||||||
return [__("To Receive"), "orange",
|
return [__("To Receive"), "orange",
|
||||||
"per_received,<,100|per_billed,=,100|status,!=,Stopped"];
|
"per_received,<,100|per_billed,=,100|status,!=,Stopped"];
|
||||||
}
|
}
|
||||||
} else if(flt(doc.per_received) == 100 && flt(doc.per_billed) < 100 && doc.status!=="Stopped") {
|
} else if(flt(doc.per_received, 2) == 100 && flt(doc.per_billed, 2) < 100 && doc.status!=="Stopped") {
|
||||||
return [__("To Bill"), "orange", "per_received,=,100|per_billed,<,100|status,!=,Stopped"];
|
return [__("To Bill"), "orange", "per_received,=,100|per_billed,<,100|status,!=,Stopped"];
|
||||||
} else if(flt(doc.per_received) == 100 && flt(doc.per_billed) == 100 && doc.status!=="Stopped") {
|
} else if(flt(doc.per_received, 2) == 100 && flt(doc.per_billed, 2) == 100 && doc.status!=="Stopped") {
|
||||||
return [__("Completed"), "green", "per_received,=,100|per_billed,=,100|status,!=,Stopped"];
|
return [__("Completed"), "green", "per_received,=,100|per_billed,=,100|status,!=,Stopped"];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
8
erpnext/change_log/v6/v6_3_0.md
Normal file
8
erpnext/change_log/v6/v6_3_0.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
- **Tax Rule:** Define rules to automatically select a Tax Template based on Customer, Supplier, Billing Address or Shipping Address
|
||||||
|
- Changes to **Shopping Cart:**
|
||||||
|
- The prices will be based on only a single Price List defined in Shopping Cart Settings. Essentially, it means that your Shopping Cart will be available only in a single currency.
|
||||||
|
- Shipping Rule will be defined per Country, instead of Territory.
|
||||||
|
- Taxes will be applied based on the new Tax Rule system, instead of Territory.
|
||||||
|
- **Important Note:** Your Shopping Cart Settings have been disabled. The new changes require you to review your Price List, Tax Rules and Shipping Rule, update the settings, and then enable Shopping Cart again.
|
||||||
|
- Enhancements in Customer Portal user interface
|
||||||
|
- Sales Team is now editable after submission of Sales Order, Sales Invoice and Delivery Note
|
@ -106,6 +106,11 @@ def get_data():
|
|||||||
"name": "Accounts Settings",
|
"name": "Accounts Settings",
|
||||||
"description": _("Default settings for accounting transactions.")
|
"description": _("Default settings for accounting transactions.")
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "doctype",
|
||||||
|
"name": "Tax Rule",
|
||||||
|
"description": _("Tax Rule for transactions.")
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Sales Taxes and Charges Template",
|
"name": "Sales Taxes and Charges Template",
|
||||||
|
@ -167,6 +167,9 @@ class AccountsController(TransactionBase):
|
|||||||
if ret.get("pricing_rule_for") == "Price":
|
if ret.get("pricing_rule_for") == "Price":
|
||||||
item.set("pricing_list_rate", ret.get("pricing_list_rate"))
|
item.set("pricing_list_rate", ret.get("pricing_list_rate"))
|
||||||
|
|
||||||
|
if item.price_list_rate:
|
||||||
|
item.rate = flt(item.price_list_rate *
|
||||||
|
(1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
|
||||||
|
|
||||||
def set_taxes(self):
|
def set_taxes(self):
|
||||||
if not self.meta.get_field("taxes"):
|
if not self.meta.get_field("taxes"):
|
||||||
|
@ -21,37 +21,57 @@ def get_list_context(context=None):
|
|||||||
def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20):
|
def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20):
|
||||||
from frappe.templates.pages.list import get_list
|
from frappe.templates.pages.list import get_list
|
||||||
user = frappe.session.user
|
user = frappe.session.user
|
||||||
|
key = None
|
||||||
|
|
||||||
|
if not filters: filters = []
|
||||||
|
|
||||||
|
filters.append((doctype, "docstatus", "=", 1))
|
||||||
|
|
||||||
if user != "Guest" and is_website_user():
|
if user != "Guest" and is_website_user():
|
||||||
# find party for this contact
|
# find party for this contact
|
||||||
customers, suppliers = get_customers_suppliers(doctype, user)
|
customers, suppliers = get_customers_suppliers(doctype, user)
|
||||||
|
|
||||||
if customers:
|
if customers:
|
||||||
return post_process(get_list(doctype, txt, filters=[(doctype, "customer", "in", customers)],
|
key, parties = "customer", customers
|
||||||
limit_start=limit_start, limit_page_length=limit_page_length, ignore_permissions=True))
|
|
||||||
|
|
||||||
elif suppliers:
|
elif suppliers:
|
||||||
return post_process(get_list(doctype, txt, filters=[(doctype, "supplier", "in", suppliers)],
|
key, parties = "supplier", suppliers
|
||||||
limit_start=limit_start, limit_page_length=limit_page_length, ignore_permissions=True))
|
|
||||||
|
|
||||||
|
filters.append((doctype, key, "in", parties))
|
||||||
|
|
||||||
|
if key:
|
||||||
|
return post_process(doctype, get_list(doctype, txt,
|
||||||
|
filters=filters, fields = "name",
|
||||||
|
limit_start=limit_start, limit_page_length=limit_page_length,
|
||||||
|
ignore_permissions=True,
|
||||||
|
order_by = "modified desc"))
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
return post_process(get_list(doctype, txt, filters, limit_start, limit_page_length))
|
return post_process(doctype, get_list(doctype, txt, filters, limit_start, limit_page_length,
|
||||||
|
fields="name", order_by = "modified desc"))
|
||||||
|
|
||||||
def post_process(result):
|
def post_process(doctype, data):
|
||||||
for r in result:
|
result = []
|
||||||
r.status_percent = 0
|
for d in data:
|
||||||
r.status_display = []
|
doc = frappe.get_doc(doctype, d.name)
|
||||||
|
|
||||||
if r.get("per_billed"):
|
doc.status_percent = 0
|
||||||
r.status_percent += flt(r.per_billed)
|
doc.status_display = []
|
||||||
r.status_display.append(_("Billed") if r.per_billed==100 else _("{0}% Billed").format(r.per_billed))
|
|
||||||
|
|
||||||
if r.get("per_delivered"):
|
if doc.get("per_billed"):
|
||||||
r.status_percent += flt(r.per_delivered)
|
doc.status_percent += flt(doc.per_billed)
|
||||||
r.status_display.append(_("Delivered") if r.per_delivered==100 else _("{0}% Delivered").format(r.per_delivered))
|
doc.status_display.append(_("Billed") if doc.per_billed==100 else _("{0}% Billed").format(doc.per_billed))
|
||||||
|
|
||||||
r.status_display = ", ".join(r.status_display)
|
if doc.get("per_delivered"):
|
||||||
|
doc.status_percent += flt(doc.per_delivered)
|
||||||
|
doc.status_display.append(_("Delivered") if doc.per_delivered==100 else _("{0}% Delivered").format(doc.per_delivered))
|
||||||
|
|
||||||
|
if hasattr(doc, "set_indicator"):
|
||||||
|
doc.set_indicator()
|
||||||
|
|
||||||
|
doc.status_display = ", ".join(doc.status_display)
|
||||||
|
doc.items_preview = ", ".join([d.item_name for d in doc.items])
|
||||||
|
result.append(doc)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
app_name = "erpnext"
|
app_name = "erpnext"
|
||||||
app_title = "ERPNext"
|
app_title = "ERPNext"
|
||||||
app_publisher = "Frappe Technologies Pvt. Ltd."
|
app_publisher = "Frappe Technologies Pvt. Ltd."
|
||||||
@ -27,7 +29,7 @@ blogs.
|
|||||||
"""
|
"""
|
||||||
app_icon = "icon-th"
|
app_icon = "icon-th"
|
||||||
app_color = "#e74c3c"
|
app_color = "#e74c3c"
|
||||||
app_version = "6.2.0"
|
app_version = "6.3.0"
|
||||||
github_link = "https://github.com/frappe/erpnext"
|
github_link = "https://github.com/frappe/erpnext"
|
||||||
|
|
||||||
error_report_email = "support@erpnext.com"
|
error_report_email = "support@erpnext.com"
|
||||||
@ -62,11 +64,26 @@ website_context = {
|
|||||||
|
|
||||||
website_route_rules = [
|
website_route_rules = [
|
||||||
{"from_route": "/orders", "to_route": "Sales Order"},
|
{"from_route": "/orders", "to_route": "Sales Order"},
|
||||||
{"from_route": "/orders/<path:name>", "to_route": "print", "defaults": {"doctype": "Sales Order"}},
|
{"from_route": "/orders/<path:name>", "to_route": "order",
|
||||||
|
"defaults": {
|
||||||
|
"doctype": "Sales Order",
|
||||||
|
"parents": [{"title": _("Orders"), "name": "orders"}]
|
||||||
|
}
|
||||||
|
},
|
||||||
{"from_route": "/invoices", "to_route": "Sales Invoice"},
|
{"from_route": "/invoices", "to_route": "Sales Invoice"},
|
||||||
{"from_route": "/invoices/<path:name>", "to_route": "print", "defaults": {"doctype": "Sales Invoice"}},
|
{"from_route": "/invoices/<path:name>", "to_route": "order",
|
||||||
|
"defaults": {
|
||||||
|
"doctype": "Sales Invoice",
|
||||||
|
"parents": [{"title": _("Invoices"), "name": "invoices"}]
|
||||||
|
}
|
||||||
|
},
|
||||||
{"from_route": "/shipments", "to_route": "Delivery Note"},
|
{"from_route": "/shipments", "to_route": "Delivery Note"},
|
||||||
{"from_route": "/shipments/<path:name>", "to_route": "print", "defaults": {"doctype": "Delivery Note"}}
|
{"from_route": "/shipments/<path:name>", "to_route": "order",
|
||||||
|
"defaults": {
|
||||||
|
"doctype": "Delivery Notes",
|
||||||
|
"parents": [{"title": _("Shipments"), "name": "shipments"}]
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
has_website_permission = {
|
has_website_permission = {
|
||||||
|
@ -89,7 +89,7 @@ class Employee(Document):
|
|||||||
user.user_image = self.image
|
user.user_image = self.image
|
||||||
try:
|
try:
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "File Data",
|
"doctype": "File",
|
||||||
"file_name": self.image,
|
"file_name": self.image,
|
||||||
"attached_to_doctype": "User",
|
"attached_to_doctype": "User",
|
||||||
"attached_to_name": self.user_id
|
"attached_to_name": self.user_id
|
||||||
|
@ -147,7 +147,7 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, dt, dn) {
|
|||||||
cur_frm.fields_dict['items'].grid.get_field('item_code').get_query = function(doc) {
|
cur_frm.fields_dict['items'].grid.get_field('item_code').get_query = function(doc) {
|
||||||
return{
|
return{
|
||||||
query: "erpnext.controllers.queries.item_query",
|
query: "erpnext.controllers.queries.item_query",
|
||||||
filters: [["Item", "name", "!=", doc.item]]
|
filters: [["Item", "name", "!=", cur_frm.doc.item]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,56 +2,13 @@
|
|||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"autoname": "field:operation",
|
"autoname": "Prompt",
|
||||||
"creation": "2014-11-07 16:20:30.683186",
|
"creation": "2014-11-07 16:20:30.683186",
|
||||||
"custom": 0,
|
"custom": 0,
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Setup",
|
"document_type": "Setup",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "operation",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Operation",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "column_break_2",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -61,7 +18,7 @@
|
|||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 1,
|
||||||
"label": "Default Workstation",
|
"label": "Default Workstation",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Workstation",
|
"options": "Workstation",
|
||||||
@ -127,7 +84,7 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-09-14 02:55:58.575636",
|
"modified": "2015-09-23 07:32:29.550198",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Operation",
|
"name": "Operation",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"doctype": "Operation",
|
"doctype": "Operation",
|
||||||
"operation": "_Test Operation 1",
|
"name": "_Test Operation 1",
|
||||||
"workstation": "_Test Workstation 1"
|
"workstation": "_Test Workstation 1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -209,3 +209,5 @@ erpnext.patches.v6_0.fix_planned_qty
|
|||||||
erpnext.patches.v6_0.multi_currency
|
erpnext.patches.v6_0.multi_currency
|
||||||
erpnext.patches.v6_2.remove_newsletter_duplicates
|
erpnext.patches.v6_2.remove_newsletter_duplicates
|
||||||
erpnext.patches.v6_2.fix_missing_default_taxes_and_lead
|
erpnext.patches.v6_2.fix_missing_default_taxes_and_lead
|
||||||
|
erpnext.patches.v5_8.tax_rule
|
||||||
|
erpnext.patches.v6_3.convert_applicable_territory
|
||||||
|
@ -9,7 +9,7 @@ def execute():
|
|||||||
"Blog Category", "Blog Settings", "Blogger", "Branch", "Brand", "Buying Settings",
|
"Blog Category", "Blog Settings", "Blogger", "Branch", "Brand", "Buying Settings",
|
||||||
"Comment", "Communication", "Company", "Contact Us Settings",
|
"Comment", "Communication", "Company", "Contact Us Settings",
|
||||||
"Country", "Currency", "Currency Exchange", "Deduction Type", "Department",
|
"Country", "Currency", "Currency Exchange", "Deduction Type", "Department",
|
||||||
"Designation", "Earning Type", "Event", "Feed", "File Data", "Fiscal Year",
|
"Designation", "Earning Type", "Event", "Feed", "File", "Fiscal Year",
|
||||||
"HR Settings", "Industry Type", "Leave Type", "Letter Head",
|
"HR Settings", "Industry Type", "Leave Type", "Letter Head",
|
||||||
"Mode of Payment", "Module Def", "Naming Series", "POS Setting", "Print Heading",
|
"Mode of Payment", "Module Def", "Naming Series", "POS Setting", "Print Heading",
|
||||||
"Report", "Role", "Selling Settings", "Stock Settings", "Supplier Type", "UOM"):
|
"Report", "Role", "Selling Settings", "Stock Settings", "Supplier Type", "UOM"):
|
||||||
|
@ -4,5 +4,5 @@
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
for dt in ("Stock Ledger Entry", "Communication", "Comment", "DefaultValue", "DocShare", "File Data", "ToDo", "Feed"):
|
for dt in ("Stock Ledger Entry", "Communication", "Comment", "DefaultValue", "DocShare", "File", "ToDo", "Feed"):
|
||||||
frappe.get_doc("DocType", dt).run_module_method("on_doctype_update")
|
frappe.get_doc("DocType", dt).run_module_method("on_doctype_update")
|
@ -37,7 +37,7 @@ def fix_files_for_item(files_path, unlinked_files):
|
|||||||
frappe.db.set_value(row.doctype, row.name, "image", new_file_url, update_modified=False)
|
frappe.db.set_value(row.doctype, row.name, "image", new_file_url, update_modified=False)
|
||||||
|
|
||||||
# set it as attachment of this item code
|
# set it as attachment of this item code
|
||||||
file_data = frappe.get_doc("File Data", unlinked_files[file_url]["file"])
|
file_data = frappe.get_doc("File", unlinked_files[file_url]["file"])
|
||||||
file_data.attached_to_doctype = "Item"
|
file_data.attached_to_doctype = "Item"
|
||||||
file_data.attached_to_name = item_code
|
file_data.attached_to_name = item_code
|
||||||
file_data.save()
|
file_data.save()
|
||||||
@ -65,20 +65,20 @@ def rename_and_set_content_hash(files_path, unlinked_files, file_url):
|
|||||||
|
|
||||||
# set content hash if missing
|
# set content hash if missing
|
||||||
file_data_name = unlinked_files[file_url]["file"]
|
file_data_name = unlinked_files[file_url]["file"]
|
||||||
if not frappe.db.get_value("File Data", file_data_name, "content_hash"):
|
if not frappe.db.get_value("File", file_data_name, "content_hash"):
|
||||||
with open(new_filename, "r") as f:
|
with open(new_filename, "r") as f:
|
||||||
content_hash = get_content_hash(f.read())
|
content_hash = get_content_hash(f.read())
|
||||||
frappe.db.set_value("File Data", file_data_name, "content_hash", content_hash)
|
frappe.db.set_value("File", file_data_name, "content_hash", content_hash)
|
||||||
|
|
||||||
def get_unlinked_files(files_path):
|
def get_unlinked_files(files_path):
|
||||||
# find files that have the same name as a File Data doc
|
# find files that have the same name as a File doc
|
||||||
# and the file_name mentioned in that File Data doc doesn't exist
|
# and the file_name mentioned in that File doc doesn't exist
|
||||||
# and it isn't already attached to a doc
|
# and it isn't already attached to a doc
|
||||||
unlinked_files = {}
|
unlinked_files = {}
|
||||||
files = os.listdir(files_path)
|
files = os.listdir(files_path)
|
||||||
for file in files:
|
for file in files:
|
||||||
if not frappe.db.exists("File Data", {"file_name": file}):
|
if not frappe.db.exists("File", {"file_name": file}):
|
||||||
file_data = frappe.db.get_value("File Data", {"name": file},
|
file_data = frappe.db.get_value("File", {"name": file},
|
||||||
["file_name", "attached_to_doctype", "attached_to_name"], as_dict=True)
|
["file_name", "attached_to_doctype", "attached_to_name"], as_dict=True)
|
||||||
|
|
||||||
if (file_data
|
if (file_data
|
||||||
|
27
erpnext/patches/v5_8/tax_rule.py
Normal file
27
erpnext/patches/v5_8/tax_rule.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
customers = frappe.db.sql("""select name, default_taxes_and_charges from tabCustomer where
|
||||||
|
ifnull(default_taxes_and_charges, '') != '' """, as_dict=1)
|
||||||
|
|
||||||
|
for d in customers:
|
||||||
|
tr = frappe.new_doc("Tax Rule")
|
||||||
|
tr.tax_type = "Sales"
|
||||||
|
tr.customer = d.name
|
||||||
|
tr.sales_tax_template = d.default_taxes_and_charges
|
||||||
|
tr.save()
|
||||||
|
|
||||||
|
|
||||||
|
suppliers = frappe.db.sql("""select name, default_taxes_and_charges from tabSupplier where
|
||||||
|
ifnull(default_taxes_and_charges, '') != '' """, as_dict=1)
|
||||||
|
|
||||||
|
for d in suppliers:
|
||||||
|
tr = frappe.new_doc("Tax Rule")
|
||||||
|
tr.tax_type = "Purchase"
|
||||||
|
tr.supplier = d.name
|
||||||
|
tr.purchase_tax_template = d.default_taxes_and_charges
|
||||||
|
tr.save()
|
19
erpnext/patches/v6_3/convert_applicable_territory.py
Normal file
19
erpnext/patches/v6_3/convert_applicable_territory.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
# for price list
|
||||||
|
countries = frappe.db.sql_list("select name from tabCountry")
|
||||||
|
|
||||||
|
for doctype in ("Price List", "Shipping Rule"):
|
||||||
|
frappe.reload_doctype(doctype)
|
||||||
|
|
||||||
|
for at in frappe.db.sql("""select name, parent, territory from `tabApplicable Territory` where
|
||||||
|
parenttype = %s """, doctype, as_dict=True):
|
||||||
|
if at.territory in countries:
|
||||||
|
parent = frappe.get_doc(doctype, at.parent)
|
||||||
|
if not parent.countries:
|
||||||
|
parent.append("countries", {"country": at.territory})
|
||||||
|
parent.save()
|
||||||
|
|
||||||
|
|
||||||
|
frappe.delete_doc("DocType", "Applicable Territory")
|
@ -59,9 +59,15 @@ cur_frm.fields_dict.customer.get_query = function(doc,cdt,cdn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.fields_dict['sales_order'].get_query = function(doc) {
|
cur_frm.fields_dict['sales_order'].get_query = function(doc) {
|
||||||
|
var filters = {
|
||||||
|
'project_name': ["in", doc.__islocal ? [""] : [doc.name, ""]]
|
||||||
|
};
|
||||||
|
|
||||||
|
if (doc.customer) {
|
||||||
|
filters["customer"] = doc.customer;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
filters:{
|
filters: filters
|
||||||
'project_name': doc.name
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center top;
|
background-position: center top;
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
|
border: 1px solid #ebeff2;
|
||||||
}
|
}
|
||||||
.product-image.missing-image {
|
.product-image.missing-image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -38,6 +39,7 @@
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center top;
|
background-position: center top;
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
|
border: 1px solid #ebeff2;
|
||||||
border: 1px dashed #d1d8dd;
|
border: 1px dashed #d1d8dd;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ $.extend(shopping_cart, {
|
|||||||
args: {
|
args: {
|
||||||
item_code: opts.item_code,
|
item_code: opts.item_code,
|
||||||
qty: opts.qty,
|
qty: opts.qty,
|
||||||
with_doc: opts.with_doc || 0
|
with_items: opts.with_items || 0
|
||||||
},
|
},
|
||||||
btn: opts.btn,
|
btn: opts.btn,
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
|
@ -49,18 +49,6 @@ $.extend(erpnext, {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
add_applicable_territory: function() {
|
|
||||||
if(cur_frm.doc.__islocal && (cur_frm.doc.territories || []).length===0) {
|
|
||||||
var default_territory = frappe.defaults.get_user_default("territory");
|
|
||||||
if(default_territory) {
|
|
||||||
var territory = frappe.model.add_child(cur_frm.doc, "Applicable Territory",
|
|
||||||
"territories");
|
|
||||||
territory.territory = default_territory;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setup_serial_no: function() {
|
setup_serial_no: function() {
|
||||||
var grid_row = cur_frm.open_grid_row();
|
var grid_row = cur_frm.open_grid_row();
|
||||||
if(!grid_row.fields_dict.serial_no ||
|
if(!grid_row.fields_dict.serial_no ||
|
||||||
@ -131,8 +119,8 @@ $.extend(erpnext.utils, {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
copy_value_in_all_row: function(doc, dt, dn, table_fieldname, fieldname) {
|
copy_value_in_all_row: function(doc, dt, dn, table_fieldname, fieldname) {
|
||||||
var d = locals[dt][dn];
|
var d = locals[dt][dn];
|
||||||
if(d[fieldname]){
|
if(d[fieldname]){
|
||||||
|
@ -20,6 +20,7 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) {
|
|||||||
price_list: frm.doc.buying_price_list
|
price_list: frm.doc.buying_price_list
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
args.posting_date = frm.doc.transaction_date;
|
||||||
}
|
}
|
||||||
if(!args) return;
|
if(!args) return;
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) {
|
|||||||
|
|
||||||
erpnext.utils.get_address_display = function(frm, address_field, display_field) {
|
erpnext.utils.get_address_display = function(frm, address_field, display_field) {
|
||||||
if(frm.updating_party_details) return;
|
if(frm.updating_party_details) return;
|
||||||
|
|
||||||
if(!address_field) {
|
if(!address_field) {
|
||||||
if(frm.doc.customer) {
|
if(frm.doc.customer) {
|
||||||
address_field = "customer_address";
|
address_field = "customer_address";
|
||||||
@ -49,14 +51,32 @@ erpnext.utils.get_address_display = function(frm, address_field, display_field)
|
|||||||
address_field = "supplier_address";
|
address_field = "supplier_address";
|
||||||
} else return;
|
} else return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!display_field) display_field = "address_display";
|
if(!display_field) display_field = "address_display";
|
||||||
if(frm.doc[address_field]) {
|
if(frm.doc[address_field]) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.utilities.doctype.address.address.get_address_display",
|
method: "erpnext.utilities.doctype.address.address.get_address_display",
|
||||||
args: {"address_dict": frm.doc[address_field] },
|
args: {"address_dict": frm.doc[address_field] },
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(r.message)
|
if(r.message){
|
||||||
frm.set_value(display_field, r.message)
|
frm.set_value(display_field, r.message)
|
||||||
|
}
|
||||||
|
frappe.call({
|
||||||
|
method: "erpnext.accounts.party.set_taxes",
|
||||||
|
args: {
|
||||||
|
"party": frm.doc.customer || frm.doc.supplier,
|
||||||
|
"party_type": (frm.doc.customer ? "Customer" : "Supplier"),
|
||||||
|
"posting_date": frm.doc.posting_date || frm.doc.transaction_date,
|
||||||
|
"company": frm.doc.company,
|
||||||
|
"billing_address": ((frm.doc.customer) ? (frm.doc.customer_address) : (frm.doc.supplier_address)),
|
||||||
|
"shipping_address": frm.doc.shipping_address_name
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if(r.message){
|
||||||
|
frm.set_value("taxes_and_charges", r.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
@border-color: #d1d8dd;
|
@border-color: #d1d8dd;
|
||||||
|
@light-border-color: #EBEFF2;
|
||||||
|
|
||||||
.web-long-description {
|
.web-long-description {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
@ -35,6 +36,7 @@
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center top;
|
background-position: center top;
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
|
border: 1px solid @light-border-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.product-image.missing-image {
|
.product-image.missing-image {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,17 +1,20 @@
|
|||||||
frappe.listview_settings['Sales Order'] = {
|
frappe.listview_settings['Sales Order'] = {
|
||||||
add_fields: ["base_grand_total", "customer_name", "currency", "delivery_date", "per_delivered", "per_billed",
|
add_fields: ["base_grand_total", "customer_name", "currency", "delivery_date", "per_delivered", "per_billed",
|
||||||
"status"],
|
"status", "order_type"],
|
||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if(doc.status==="Stopped") {
|
if(doc.status==="Stopped") {
|
||||||
return [__("Stopped"), "darkgrey", "status,=,Stopped"];
|
return [__("Stopped"), "darkgrey", "status,=,Stopped"];
|
||||||
} else if(flt(doc.per_delivered) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
|
||||||
|
} else if (doc.order_type !== "Maintenance"
|
||||||
|
&& flt(doc.per_delivered, 2) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
||||||
// to bill & overdue
|
// to bill & overdue
|
||||||
return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Stopped"];
|
return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Stopped"];
|
||||||
|
|
||||||
} else if(flt(doc.per_delivered) < 100 && doc.status!=="Stopped") {
|
} else if (doc.order_type !== "Maintenance"
|
||||||
|
&& flt(doc.per_delivered, 2) < 100 && doc.status!=="Stopped") {
|
||||||
// not delivered
|
// not delivered
|
||||||
|
|
||||||
if(flt(doc.per_billed) < 100) {
|
if(flt(doc.per_billed, 2) < 100) {
|
||||||
// not delivered & not billed
|
// not delivered & not billed
|
||||||
|
|
||||||
return [__("To Deliver and Bill"), "orange",
|
return [__("To Deliver and Bill"), "orange",
|
||||||
@ -23,11 +26,14 @@ frappe.listview_settings['Sales Order'] = {
|
|||||||
"per_delivered,<,100|per_billed,=,100|status,!=,Stopped"];
|
"per_delivered,<,100|per_billed,=,100|status,!=,Stopped"];
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if(flt(doc.per_delivered) == 100 && flt(doc.per_billed) < 100 && doc.status!=="Stopped") {
|
} else if ((doc.order_type === "Maintenance" || flt(doc.per_delivered, 2) == 100)
|
||||||
|
&& flt(doc.per_billed, 2) < 100 && doc.status!=="Stopped") {
|
||||||
|
|
||||||
// to bill
|
// to bill
|
||||||
return [__("To Bill"), "orange", "per_delivered,=,100|per_billed,<,100|status,!=,Stopped"];
|
return [__("To Bill"), "orange", "per_delivered,=,100|per_billed,<,100|status,!=,Stopped"];
|
||||||
|
|
||||||
} else if(flt(doc.per_delivered) == 100 && flt(doc.per_billed) == 100 && doc.status!=="Stopped") {
|
} else if((doc.order_type === "Maintenance" || flt(doc.per_delivered, 2) == 100)
|
||||||
|
&& flt(doc.per_billed, 2) == 100 && doc.status!=="Stopped") {
|
||||||
|
|
||||||
return [__("Completed"), "green", "per_delivered,=,100|per_billed,=,100|status,!=,Stopped"];
|
return [__("Completed"), "green", "per_delivered,=,100|per_billed,=,100|status,!=,Stopped"];
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "sales_person",
|
"fieldname": "sales_person",
|
||||||
@ -34,7 +34,7 @@
|
|||||||
"width": "200px"
|
"width": "200px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "contact_no",
|
"fieldname": "contact_no",
|
||||||
@ -79,7 +79,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "allocated_percentage",
|
"fieldname": "allocated_percentage",
|
||||||
@ -104,7 +104,7 @@
|
|||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "allocated_amount",
|
"fieldname": "allocated_amount",
|
||||||
@ -130,7 +130,7 @@
|
|||||||
"width": "120px"
|
"width": "120px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "incentives",
|
"fieldname": "incentives",
|
||||||
@ -185,7 +185,7 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2015-08-13 16:30:24.146848",
|
"modified": "2015-09-23 09:50:26.923187",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Team",
|
"name": "Sales Team",
|
||||||
|
@ -4,5 +4,11 @@
|
|||||||
"doctype": "Customer Group",
|
"doctype": "Customer Group",
|
||||||
"is_group": "No",
|
"is_group": "No",
|
||||||
"parent_customer_group": "All Customer Groups"
|
"parent_customer_group": "All Customer Groups"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"customer_group_name": "_Test Customer Group 1",
|
||||||
|
"doctype": "Customer Group",
|
||||||
|
"is_group": "No",
|
||||||
|
"parent_customer_group": "All Customer Groups"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -174,10 +174,7 @@ def create_price_lists(args):
|
|||||||
"enabled": 1,
|
"enabled": 1,
|
||||||
"buying": 1 if pl_type == "Buying" else 0,
|
"buying": 1 if pl_type == "Buying" else 0,
|
||||||
"selling": 1 if pl_type == "Selling" else 0,
|
"selling": 1 if pl_type == "Selling" else 0,
|
||||||
"currency": args["currency"],
|
"currency": args["currency"]
|
||||||
"territories": [{
|
|
||||||
"territory": get_root_of("Territory")
|
|
||||||
}]
|
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
def set_defaults(args):
|
def set_defaults(args):
|
||||||
@ -304,7 +301,7 @@ def get_fy_details(fy_start_date, fy_end_date):
|
|||||||
return fy
|
return fy
|
||||||
|
|
||||||
def create_taxes(args):
|
def create_taxes(args):
|
||||||
|
|
||||||
for i in xrange(1,6):
|
for i in xrange(1,6):
|
||||||
if args.get("tax_" + str(i)):
|
if args.get("tax_" + str(i)):
|
||||||
# replace % in case someone also enters the % symbol
|
# replace % in case someone also enters the % symbol
|
||||||
@ -324,7 +321,7 @@ def create_taxes(args):
|
|||||||
raise
|
raise
|
||||||
except RootNotEditable, e:
|
except RootNotEditable, e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def make_tax_head(args, i, tax_group, tax_rate):
|
def make_tax_head(args, i, tax_group, tax_rate):
|
||||||
return frappe.get_doc({
|
return frappe.get_doc({
|
||||||
"doctype":"Account",
|
"doctype":"Account",
|
||||||
|
@ -1,103 +1,2 @@
|
|||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
from frappe import _
|
|
||||||
from frappe.utils import get_fullname, flt
|
|
||||||
from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import check_shopping_cart_enabled, get_default_territory
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
# validate stock of each item in Website Warehouse or have a list of possible warehouses in Shopping Cart Settings
|
|
||||||
# Below functions are used for test cases
|
|
||||||
|
|
||||||
def get_quotation(user=None):
|
|
||||||
if not user:
|
|
||||||
user = frappe.session.user
|
|
||||||
if user == "Guest":
|
|
||||||
raise frappe.PermissionError
|
|
||||||
|
|
||||||
check_shopping_cart_enabled()
|
|
||||||
party = get_party(user)
|
|
||||||
values = {
|
|
||||||
"order_type": "Shopping Cart",
|
|
||||||
party.doctype.lower(): party.name,
|
|
||||||
"docstatus": 0,
|
|
||||||
"contact_email": user,
|
|
||||||
"selling_price_list": "_Test Price List Rest of the World",
|
|
||||||
"currency": "USD"
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
quotation = frappe.get_doc("Quotation", values)
|
|
||||||
|
|
||||||
except frappe.DoesNotExistError:
|
|
||||||
quotation = frappe.new_doc("Quotation")
|
|
||||||
quotation.update(values)
|
|
||||||
if party.doctype == "Customer":
|
|
||||||
quotation.contact_person = frappe.db.get_value("Contact", {"customer": party.name, "email_id": user})
|
|
||||||
quotation.insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
return quotation
|
|
||||||
|
|
||||||
def set_item_in_cart(item_code, qty, user=None):
|
|
||||||
validate_item(item_code)
|
|
||||||
quotation = get_quotation(user=user)
|
|
||||||
qty = flt(qty)
|
|
||||||
quotation_item = quotation.get("items", {"item_code": item_code})
|
|
||||||
if qty==0:
|
|
||||||
if quotation_item:
|
|
||||||
# remove
|
|
||||||
quotation.get("items").remove(quotation_item[0])
|
|
||||||
else:
|
|
||||||
# add or update
|
|
||||||
if quotation_item:
|
|
||||||
quotation_item[0].qty = qty
|
|
||||||
else:
|
|
||||||
quotation.append("items", {
|
|
||||||
"doctype": "Quotation Item",
|
|
||||||
"item_code": item_code,
|
|
||||||
"qty": qty
|
|
||||||
})
|
|
||||||
quotation.save(ignore_permissions=True)
|
|
||||||
return quotation
|
|
||||||
|
|
||||||
def validate_item(item_code):
|
|
||||||
item = frappe.db.get_value("Item", item_code, ["item_name", "show_in_website"], as_dict=True)
|
|
||||||
if not item.show_in_website:
|
|
||||||
frappe.throw(_("{0} cannot be purchased using Shopping Cart").format(item.item_name))
|
|
||||||
|
|
||||||
def get_party(user):
|
|
||||||
def _get_party(user):
|
|
||||||
customer = frappe.db.get_value("Contact", {"email_id": user}, "customer")
|
|
||||||
if customer:
|
|
||||||
return frappe.get_doc("Customer", customer)
|
|
||||||
|
|
||||||
lead = frappe.db.get_value("Lead", {"email_id": user})
|
|
||||||
if lead:
|
|
||||||
return frappe.get_doc("Lead", lead)
|
|
||||||
|
|
||||||
# create a lead
|
|
||||||
lead = frappe.new_doc("Lead")
|
|
||||||
lead.update({
|
|
||||||
"email_id": user,
|
|
||||||
"lead_name": get_fullname(user),
|
|
||||||
"territory": guess_territory()
|
|
||||||
})
|
|
||||||
lead.insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
return lead
|
|
||||||
|
|
||||||
if not getattr(frappe.local, "shopping_cart_party", None):
|
|
||||||
frappe.local.shopping_cart_party = {}
|
|
||||||
|
|
||||||
if not frappe.local.shopping_cart_party.get(user):
|
|
||||||
frappe.local.shopping_cart_party[user] = _get_party(user)
|
|
||||||
|
|
||||||
return frappe.local.shopping_cart_party[user]
|
|
||||||
|
|
||||||
def guess_territory():
|
|
||||||
territory = None
|
|
||||||
if frappe.session.get("session_country"):
|
|
||||||
territory = frappe.db.get_value("Territory", frappe.session.get("session_country"))
|
|
||||||
return territory or get_default_territory()
|
|
||||||
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import throw, _
|
from frappe import throw, _
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
from frappe.utils import cint, flt, get_fullname, fmt_money, cstr
|
from frappe.utils import cint, flt, get_fullname, cstr
|
||||||
from erpnext.utilities.doctype.address.address import get_address_display
|
from erpnext.utilities.doctype.address.address import get_address_display
|
||||||
from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import get_shopping_cart_settings
|
from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import get_shopping_cart_settings
|
||||||
from frappe.utils.nestedset import get_root_of
|
from frappe.utils.nestedset import get_root_of
|
||||||
@ -17,11 +17,13 @@ def set_cart_count(quotation=None):
|
|||||||
if not quotation:
|
if not quotation:
|
||||||
quotation = _get_cart_quotation()
|
quotation = _get_cart_quotation()
|
||||||
cart_count = cstr(len(quotation.get("items")))
|
cart_count = cstr(len(quotation.get("items")))
|
||||||
frappe.local.cookie_manager.set_cookie("cart_count", cart_count)
|
|
||||||
|
if hasattr(frappe.local, "cookie_manager"):
|
||||||
|
frappe.local.cookie_manager.set_cookie("cart_count", cart_count)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_cart_quotation(doc=None):
|
def get_cart_quotation(doc=None):
|
||||||
party = get_lead_or_customer()
|
party = get_customer()
|
||||||
|
|
||||||
if not doc:
|
if not doc:
|
||||||
quotation = _get_cart_quotation(party)
|
quotation = _get_cart_quotation(party)
|
||||||
@ -58,21 +60,19 @@ def place_order():
|
|||||||
sales_order.flags.ignore_permissions = True
|
sales_order.flags.ignore_permissions = True
|
||||||
sales_order.insert()
|
sales_order.insert()
|
||||||
sales_order.submit()
|
sales_order.submit()
|
||||||
frappe.local.cookie_manager.delete_cookie("cart_count")
|
|
||||||
|
if hasattr(frappe.local, "cookie_manager"):
|
||||||
|
frappe.local.cookie_manager.delete_cookie("cart_count")
|
||||||
|
|
||||||
return sales_order.name
|
return sales_order.name
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def update_cart(item_code, qty, with_doc):
|
def update_cart(item_code, qty, with_items=False):
|
||||||
quotation = _get_cart_quotation()
|
quotation = _get_cart_quotation()
|
||||||
|
|
||||||
qty = flt(qty)
|
qty = flt(qty)
|
||||||
if qty == 0:
|
if qty == 0:
|
||||||
quotation.set("items", quotation.get("items", {"item_code": ["!=", item_code]}))
|
quotation.set("items", quotation.get("items", {"item_code": ["!=", item_code]}))
|
||||||
if not quotation.get("items") and \
|
|
||||||
not quotation.get("__islocal"):
|
|
||||||
quotation.__delete = True
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
quotation_items = quotation.get("items", {"item_code": item_code})
|
quotation_items = quotation.get("items", {"item_code": item_code})
|
||||||
if not quotation_items:
|
if not quotation_items:
|
||||||
@ -86,17 +86,19 @@ def update_cart(item_code, qty, with_doc):
|
|||||||
|
|
||||||
apply_cart_settings(quotation=quotation)
|
apply_cart_settings(quotation=quotation)
|
||||||
|
|
||||||
if hasattr(quotation, "__delete"):
|
quotation.flags.ignore_permissions = True
|
||||||
frappe.delete_doc("Quotation", quotation.name, ignore_permissions=True)
|
quotation.save()
|
||||||
quotation = _get_cart_quotation()
|
|
||||||
else:
|
|
||||||
quotation.flags.ignore_permissions = True
|
|
||||||
quotation.save()
|
|
||||||
|
|
||||||
set_cart_count(quotation)
|
set_cart_count(quotation)
|
||||||
|
|
||||||
if with_doc:
|
if with_items:
|
||||||
return get_cart_quotation(quotation)
|
context = get_cart_quotation(quotation)
|
||||||
|
return {
|
||||||
|
"items": frappe.render_template("templates/includes/cart/cart_items.html",
|
||||||
|
context),
|
||||||
|
"taxes": frappe.render_template("templates/includes/order/order_taxes.html",
|
||||||
|
context),
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
return quotation.name
|
return quotation.name
|
||||||
|
|
||||||
@ -122,7 +124,11 @@ def update_cart_address(address_fieldname, address_name):
|
|||||||
quotation.flags.ignore_permissions = True
|
quotation.flags.ignore_permissions = True
|
||||||
quotation.save()
|
quotation.save()
|
||||||
|
|
||||||
return get_cart_quotation(quotation)
|
context = get_cart_quotation(quotation)
|
||||||
|
return {
|
||||||
|
"taxes": frappe.render_template("templates/includes/order/order_taxes.html",
|
||||||
|
context),
|
||||||
|
}
|
||||||
|
|
||||||
def guess_territory():
|
def guess_territory():
|
||||||
territory = None
|
territory = None
|
||||||
@ -134,32 +140,23 @@ def guess_territory():
|
|||||||
frappe.db.get_value("Shopping Cart Settings", None, "territory") or \
|
frappe.db.get_value("Shopping Cart Settings", None, "territory") or \
|
||||||
get_root_of("Territory")
|
get_root_of("Territory")
|
||||||
|
|
||||||
def decorate_quotation_doc(quotation_doc):
|
def decorate_quotation_doc(doc):
|
||||||
doc = frappe._dict(quotation_doc.as_dict())
|
|
||||||
for d in doc.get("items", []):
|
for d in doc.get("items", []):
|
||||||
d.update(frappe.db.get_value("Item", d["item_code"],
|
d.update(frappe.db.get_value("Item", d.item_code,
|
||||||
["website_image", "description", "page_name"], as_dict=True))
|
["website_image", "description", "page_name"], as_dict=True))
|
||||||
d["formatted_rate"] = fmt_money(d.get("rate"), currency=doc.currency)
|
|
||||||
d["formatted_amount"] = fmt_money(d.get("amount"), currency=doc.currency)
|
|
||||||
|
|
||||||
for d in doc.get("taxes", []):
|
|
||||||
d["formatted_tax_amount"] = fmt_money(flt(d.get("tax_amount_after_discount_amount")),
|
|
||||||
currency=doc.currency)
|
|
||||||
|
|
||||||
doc.formatted_grand_total_export = fmt_money(doc.grand_total,
|
|
||||||
currency=doc.currency)
|
|
||||||
|
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
def _get_cart_quotation(party=None):
|
def _get_cart_quotation(party=None):
|
||||||
if not party:
|
if not party:
|
||||||
party = get_lead_or_customer()
|
party = get_customer()
|
||||||
|
|
||||||
quotation = frappe.db.get_value("Quotation",
|
quotation = frappe.get_all("Quotation", fields=["name"], filters=
|
||||||
{party.doctype.lower(): party.name, "order_type": "Shopping Cart", "docstatus": 0})
|
{party.doctype.lower(): party.name, "order_type": "Shopping Cart", "docstatus": 0},
|
||||||
|
order_by="modified desc", limit_page_length=1)
|
||||||
|
|
||||||
if quotation:
|
if quotation:
|
||||||
qdoc = frappe.get_doc("Quotation", quotation)
|
qdoc = frappe.get_doc("Quotation", quotation[0].name)
|
||||||
else:
|
else:
|
||||||
qdoc = frappe.get_doc({
|
qdoc = frappe.get_doc({
|
||||||
"doctype": "Quotation",
|
"doctype": "Quotation",
|
||||||
@ -173,9 +170,9 @@ def _get_cart_quotation(party=None):
|
|||||||
(party.doctype.lower()): party.name
|
(party.doctype.lower()): party.name
|
||||||
})
|
})
|
||||||
|
|
||||||
if party.doctype == "Customer":
|
qdoc.contact_person = frappe.db.get_value("Contact", {"email_id": frappe.session.user,
|
||||||
qdoc.contact_person = frappe.db.get_value("Contact", {"email_id": frappe.session.user,
|
"customer": party.name})
|
||||||
"customer": party.name})
|
qdoc.contact_email = frappe.session.user
|
||||||
|
|
||||||
qdoc.flags.ignore_permissions = True
|
qdoc.flags.ignore_permissions = True
|
||||||
qdoc.run_method("set_missing_values")
|
qdoc.run_method("set_missing_values")
|
||||||
@ -184,27 +181,21 @@ def _get_cart_quotation(party=None):
|
|||||||
return qdoc
|
return qdoc
|
||||||
|
|
||||||
def update_party(fullname, company_name=None, mobile_no=None, phone=None):
|
def update_party(fullname, company_name=None, mobile_no=None, phone=None):
|
||||||
party = get_lead_or_customer()
|
party = get_customer()
|
||||||
|
|
||||||
if party.doctype == "Lead":
|
party.customer_name = company_name or fullname
|
||||||
party.company_name = company_name
|
party.customer_type == "Company" if company_name else "Individual"
|
||||||
party.lead_name = fullname
|
|
||||||
party.mobile_no = mobile_no
|
|
||||||
party.phone = phone
|
|
||||||
else:
|
|
||||||
party.customer_name = company_name or fullname
|
|
||||||
party.customer_type == "Company" if company_name else "Individual"
|
|
||||||
|
|
||||||
contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user,
|
contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user,
|
||||||
"customer": party.name})
|
"customer": party.name})
|
||||||
contact = frappe.get_doc("Contact", contact_name)
|
contact = frappe.get_doc("Contact", contact_name)
|
||||||
contact.first_name = fullname
|
contact.first_name = fullname
|
||||||
contact.last_name = None
|
contact.last_name = None
|
||||||
contact.customer_name = party.customer_name
|
contact.customer_name = party.customer_name
|
||||||
contact.mobile_no = mobile_no
|
contact.mobile_no = mobile_no
|
||||||
contact.phone = phone
|
contact.phone = phone
|
||||||
contact.flags.ignore_permissions = True
|
contact.flags.ignore_permissions = True
|
||||||
contact.save()
|
contact.save()
|
||||||
|
|
||||||
party_doc = frappe.get_doc(party.as_dict())
|
party_doc = frappe.get_doc(party.as_dict())
|
||||||
party_doc.flags.ignore_permissions = True
|
party_doc.flags.ignore_permissions = True
|
||||||
@ -219,26 +210,24 @@ def update_party(fullname, company_name=None, mobile_no=None, phone=None):
|
|||||||
|
|
||||||
def apply_cart_settings(party=None, quotation=None):
|
def apply_cart_settings(party=None, quotation=None):
|
||||||
if not party:
|
if not party:
|
||||||
party = get_lead_or_customer()
|
party = get_customer()
|
||||||
if not quotation:
|
if not quotation:
|
||||||
quotation = _get_cart_quotation(party)
|
quotation = _get_cart_quotation(party)
|
||||||
|
|
||||||
cart_settings = frappe.get_doc("Shopping Cart Settings")
|
cart_settings = frappe.get_doc("Shopping Cart Settings")
|
||||||
billing_territory = get_address_territory(quotation.customer_address) or \
|
|
||||||
party.territory or get_root_of("Territory")
|
|
||||||
|
|
||||||
set_price_list_and_rate(quotation, cart_settings, billing_territory)
|
set_price_list_and_rate(quotation, cart_settings)
|
||||||
|
|
||||||
quotation.run_method("calculate_taxes_and_totals")
|
quotation.run_method("calculate_taxes_and_totals")
|
||||||
|
|
||||||
set_taxes(quotation, cart_settings, billing_territory)
|
set_taxes(quotation, cart_settings)
|
||||||
|
|
||||||
_apply_shipping_rule(party, quotation, cart_settings)
|
_apply_shipping_rule(party, quotation, cart_settings)
|
||||||
|
|
||||||
def set_price_list_and_rate(quotation, cart_settings, billing_territory):
|
def set_price_list_and_rate(quotation, cart_settings):
|
||||||
"""set price list based on billing territory"""
|
"""set price list based on billing territory"""
|
||||||
|
|
||||||
_set_price_list(quotation, cart_settings, billing_territory)
|
_set_price_list(quotation, cart_settings)
|
||||||
|
|
||||||
# reset values
|
# reset values
|
||||||
quotation.price_list_currency = quotation.currency = \
|
quotation.price_list_currency = quotation.currency = \
|
||||||
@ -249,57 +238,75 @@ def set_price_list_and_rate(quotation, cart_settings, billing_territory):
|
|||||||
# refetch values
|
# refetch values
|
||||||
quotation.run_method("set_price_list_and_item_details")
|
quotation.run_method("set_price_list_and_item_details")
|
||||||
|
|
||||||
# set it in cookies for using in product page
|
if hasattr(frappe.local, "cookie_manager"):
|
||||||
frappe.local.cookie_manager.set_cookie("selling_price_list", quotation.selling_price_list)
|
# set it in cookies for using in product page
|
||||||
|
frappe.local.cookie_manager.set_cookie("selling_price_list", quotation.selling_price_list)
|
||||||
|
|
||||||
|
def _set_price_list(quotation, cart_settings):
|
||||||
|
"""Set price list based on customer or shopping cart default"""
|
||||||
|
if quotation.selling_price_list:
|
||||||
|
return
|
||||||
|
|
||||||
def _set_price_list(quotation, cart_settings, billing_territory):
|
|
||||||
# check if customer price list exists
|
# check if customer price list exists
|
||||||
selling_price_list = None
|
selling_price_list = None
|
||||||
if quotation.customer:
|
if quotation.customer:
|
||||||
selling_price_list = frappe.db.get_value("Customer", quotation.customer, "default_price_list")
|
from erpnext.accounts.party import get_default_price_list
|
||||||
|
selling_price_list = get_default_price_list(frappe.get_doc("Customer", quotation.customer))
|
||||||
|
|
||||||
# else check for territory based price list
|
# else check for territory based price list
|
||||||
if not selling_price_list:
|
if not selling_price_list:
|
||||||
selling_price_list = cart_settings.get_price_list(billing_territory)
|
selling_price_list = cart_settings.price_list
|
||||||
|
|
||||||
quotation.selling_price_list = selling_price_list
|
quotation.selling_price_list = selling_price_list
|
||||||
|
|
||||||
def set_taxes(quotation, cart_settings, billing_territory):
|
def set_taxes(quotation, cart_settings):
|
||||||
"""set taxes based on billing territory"""
|
"""set taxes based on billing territory"""
|
||||||
quotation.taxes_and_charges = cart_settings.get_tax_master(billing_territory)
|
from erpnext.accounts.party import set_taxes
|
||||||
|
|
||||||
# clear table
|
customer_group = frappe.db.get_value("Customer", quotation.customer, "customer_group")
|
||||||
|
|
||||||
|
quotation.taxes_and_charges = set_taxes(quotation.customer, "Customer", \
|
||||||
|
quotation.transaction_date, quotation.company, customer_group, None, \
|
||||||
|
quotation.customer_address, quotation.shipping_address_name, 1)
|
||||||
|
#
|
||||||
|
# # clear table
|
||||||
quotation.set("taxes", [])
|
quotation.set("taxes", [])
|
||||||
|
#
|
||||||
# append taxes
|
# # append taxes
|
||||||
quotation.append_taxes_from_master()
|
quotation.append_taxes_from_master()
|
||||||
|
|
||||||
def get_lead_or_customer():
|
def get_customer(user=None):
|
||||||
customer = frappe.db.get_value("Contact", {"email_id": frappe.session.user}, "customer")
|
if not user:
|
||||||
|
user = frappe.session.user
|
||||||
|
|
||||||
|
customer = frappe.db.get_value("Contact", {"email_id": user}, "customer")
|
||||||
if customer:
|
if customer:
|
||||||
return frappe.get_doc("Customer", customer)
|
return frappe.get_doc("Customer", customer)
|
||||||
|
|
||||||
lead = frappe.db.get_value("Lead", {"email_id": frappe.session.user})
|
|
||||||
if lead:
|
|
||||||
return frappe.get_doc("Lead", lead)
|
|
||||||
else:
|
else:
|
||||||
lead_doc = frappe.get_doc({
|
customer = frappe.new_doc("Customer")
|
||||||
"doctype": "Lead",
|
fullname = get_fullname(user)
|
||||||
"email_id": frappe.session.user,
|
customer.update({
|
||||||
"lead_name": get_fullname(frappe.session.user),
|
"customer_name": fullname,
|
||||||
"territory": guess_territory(),
|
"customer_type": "Individual",
|
||||||
"status": "Open" # TODO: set something better???
|
"customer_group": get_shopping_cart_settings().default_customer_group,
|
||||||
|
"territory": get_root_of("Territory")
|
||||||
})
|
})
|
||||||
|
customer.insert(ignore_permissions=True)
|
||||||
|
|
||||||
if frappe.session.user not in ("Guest", "Administrator"):
|
contact = frappe.new_doc("Contact")
|
||||||
lead_doc.flags.ignore_permissions = True
|
contact.update({
|
||||||
lead_doc.insert()
|
"customer": customer.name,
|
||||||
|
"first_name": fullname,
|
||||||
|
"email_id": user
|
||||||
|
})
|
||||||
|
contact.insert(ignore_permissions=True)
|
||||||
|
|
||||||
return lead_doc
|
return customer
|
||||||
|
|
||||||
def get_address_docs(doctype=None, txt=None, filters=None, limit_start=0, limit_page_length=20, party=None):
|
def get_address_docs(doctype=None, txt=None, filters=None, limit_start=0, limit_page_length=20, party=None):
|
||||||
if not party:
|
if not party:
|
||||||
party = get_lead_or_customer()
|
party = get_customer()
|
||||||
|
|
||||||
address_docs = frappe.db.sql("""select * from `tabAddress`
|
address_docs = frappe.db.sql("""select * from `tabAddress`
|
||||||
where `{0}`=%s order by name limit {1}, {2}""".format(party.doctype.lower(),
|
where `{0}`=%s order by name limit {1}, {2}""".format(party.doctype.lower(),
|
||||||
@ -308,7 +315,6 @@ def get_address_docs(doctype=None, txt=None, filters=None, limit_start=0, limit_
|
|||||||
|
|
||||||
for address in address_docs:
|
for address in address_docs:
|
||||||
address.display = get_address_display(address)
|
address.display = get_address_display(address)
|
||||||
address.display = (address.display).replace("\n", "<br>\n")
|
|
||||||
|
|
||||||
return address_docs
|
return address_docs
|
||||||
|
|
||||||
@ -326,38 +332,39 @@ def apply_shipping_rule(shipping_rule):
|
|||||||
return get_cart_quotation(quotation)
|
return get_cart_quotation(quotation)
|
||||||
|
|
||||||
def _apply_shipping_rule(party=None, quotation=None, cart_settings=None):
|
def _apply_shipping_rule(party=None, quotation=None, cart_settings=None):
|
||||||
shipping_rules = get_shipping_rules(party, quotation, cart_settings)
|
if not quotation.shipping_rule:
|
||||||
|
shipping_rules = get_shipping_rules(quotation, cart_settings)
|
||||||
|
|
||||||
if not shipping_rules:
|
if not shipping_rules:
|
||||||
return
|
return
|
||||||
|
|
||||||
elif quotation.shipping_rule not in shipping_rules:
|
elif quotation.shipping_rule not in shipping_rules:
|
||||||
quotation.shipping_rule = shipping_rules[0]
|
quotation.shipping_rule = shipping_rules[0]
|
||||||
|
|
||||||
quotation.run_method("apply_shipping_rule")
|
if quotation.shipping_rule:
|
||||||
quotation.run_method("calculate_taxes_and_totals")
|
quotation.run_method("apply_shipping_rule")
|
||||||
|
quotation.run_method("calculate_taxes_and_totals")
|
||||||
|
|
||||||
def get_applicable_shipping_rules(party=None, quotation=None):
|
def get_applicable_shipping_rules(party=None, quotation=None):
|
||||||
shipping_rules = get_shipping_rules(party, quotation)
|
shipping_rules = get_shipping_rules(quotation)
|
||||||
|
|
||||||
if shipping_rules:
|
if shipping_rules:
|
||||||
rule_label_map = frappe.db.get_values("Shipping Rule", shipping_rules, "label")
|
rule_label_map = frappe.db.get_values("Shipping Rule", shipping_rules, "label")
|
||||||
# we need this in sorted order as per the position of the rule in the settings page
|
# we need this in sorted order as per the position of the rule in the settings page
|
||||||
return [[rule, rule_label_map.get(rule)] for rule in shipping_rules]
|
return [[rule, rule_label_map.get(rule)] for rule in shipping_rules]
|
||||||
|
|
||||||
def get_shipping_rules(party=None, quotation=None, cart_settings=None):
|
def get_shipping_rules(quotation=None, cart_settings=None):
|
||||||
if not party:
|
|
||||||
party = get_lead_or_customer()
|
|
||||||
if not quotation:
|
if not quotation:
|
||||||
quotation = _get_cart_quotation()
|
quotation = _get_cart_quotation()
|
||||||
if not cart_settings:
|
|
||||||
cart_settings = frappe.get_doc("Shopping Cart Settings")
|
|
||||||
|
|
||||||
# set shipping rule based on shipping territory
|
shipping_rules = []
|
||||||
shipping_territory = get_address_territory(quotation.shipping_address_name) or \
|
if quotation.shipping_address_name:
|
||||||
party.territory
|
country = frappe.db.get_value("Address", quotation.shipping_address_name, "country")
|
||||||
|
if country:
|
||||||
shipping_rules = cart_settings.get_shipping_rules(shipping_territory)
|
shipping_rules = frappe.db.sql_list("""select distinct sr.name
|
||||||
|
from `tabShipping Rule Country` src, `tabShipping Rule` sr
|
||||||
|
where src.country = %s and
|
||||||
|
sr.disabled != 1 and sr.name = src.parent""", country)
|
||||||
|
|
||||||
return shipping_rules
|
return shipping_rules
|
||||||
|
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
{
|
|
||||||
"allow_copy": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"creation": "2013-06-20 16:00:18",
|
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "selling_price_list",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Price List",
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Price List",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 1,
|
|
||||||
"in_create": 0,
|
|
||||||
"in_dialog": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
|
||||||
"modified": "2013-12-20 19:30:47",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Shopping Cart",
|
|
||||||
"name": "Shopping Cart Price List",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [],
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# License: GNU General Public License v3. See license.txt
|
|
||||||
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
class ShoppingCartPriceList(Document):
|
|
||||||
pass
|
|
@ -75,17 +75,17 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"description": "<a href=\"#Sales Browser/Territory\">Add / Edit</a>",
|
"fieldname": "price_list",
|
||||||
"fieldname": "default_territory",
|
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 1,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 0,
|
||||||
"label": "Default Territory",
|
"label": "Price List",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Territory",
|
"options": "Price List",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
@ -118,7 +118,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"description": "<a href=\"#Sales Browser/Customer Group\">Add / Edit</a>",
|
"description": "",
|
||||||
"fieldname": "default_customer_group",
|
"fieldname": "default_customer_group",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -157,112 +157,6 @@
|
|||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "section_break_6",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "price_lists",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Price Lists",
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Shopping Cart Price List",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "shipping_rules",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Shipping Rules",
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Shopping Cart Shipping Rule",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "column_break_10",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "sales_taxes_and_charges_masters",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Taxes and Charges",
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Shopping Cart Taxes and Charges Master",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
@ -274,7 +168,7 @@
|
|||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-02-05 05:11:46.714019",
|
"modified": "2015-09-17 07:56:09.176098",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Shopping Cart",
|
"module": "Shopping Cart",
|
||||||
"name": "Shopping Cart Settings",
|
"name": "Shopping Cart Settings",
|
||||||
|
@ -8,8 +8,6 @@ import frappe
|
|||||||
from frappe import _, msgprint
|
from frappe import _, msgprint
|
||||||
from frappe.utils import comma_and
|
from frappe.utils import comma_and
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils.nestedset import get_ancestors_of, get_root_of
|
|
||||||
from erpnext.utilities.doctype.address.address import get_territory_from_address
|
|
||||||
|
|
||||||
class ShoppingCartSetupError(frappe.ValidationError): pass
|
class ShoppingCartSetupError(frappe.ValidationError): pass
|
||||||
|
|
||||||
@ -19,65 +17,8 @@ class ShoppingCartSettings(Document):
|
|||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if self.enabled:
|
if self.enabled:
|
||||||
self.validate_price_lists()
|
|
||||||
self.validate_tax_masters()
|
|
||||||
self.validate_exchange_rates_exist()
|
self.validate_exchange_rates_exist()
|
||||||
|
|
||||||
def validate_overlapping_territories(self, parentfield, fieldname):
|
|
||||||
# for displaying message
|
|
||||||
doctype = self.meta.get_field(parentfield).options
|
|
||||||
|
|
||||||
# specify atleast one entry in the table
|
|
||||||
self.validate_table_has_rows(parentfield, raise_exception=ShoppingCartSetupError)
|
|
||||||
|
|
||||||
territory_name_map = self.get_territory_name_map(parentfield, fieldname)
|
|
||||||
for territory, names in territory_name_map.items():
|
|
||||||
if len(names) > 1:
|
|
||||||
frappe.throw(_("{0} {1} has a common territory {2}").format(_(doctype), comma_and(names), territory), ShoppingCartSetupError)
|
|
||||||
|
|
||||||
return territory_name_map
|
|
||||||
|
|
||||||
def validate_price_lists(self):
|
|
||||||
self.validate_overlapping_territories("price_lists", "selling_price_list")
|
|
||||||
|
|
||||||
# validate that a Shopping Cart Price List exists for the default territory as a catch all!
|
|
||||||
price_list_for_default_territory = self.get_name_from_territory(self.default_territory, "price_lists",
|
|
||||||
"selling_price_list")
|
|
||||||
|
|
||||||
if not price_list_for_default_territory:
|
|
||||||
msgprint(_("Please specify a Price List which is valid for Territory") +
|
|
||||||
": " + self.default_territory, raise_exception=ShoppingCartSetupError)
|
|
||||||
|
|
||||||
def validate_tax_masters(self):
|
|
||||||
self.validate_overlapping_territories("sales_taxes_and_charges_masters",
|
|
||||||
"sales_taxes_and_charges_master")
|
|
||||||
|
|
||||||
def get_territory_name_map(self, parentfield, fieldname):
|
|
||||||
territory_name_map = {}
|
|
||||||
|
|
||||||
# entries in table
|
|
||||||
names = [doc.get(fieldname) for doc in self.get(parentfield)]
|
|
||||||
|
|
||||||
if names:
|
|
||||||
# for condition in territory check
|
|
||||||
parenttype = frappe.get_meta(self.meta.get_options(parentfield)).get_options(fieldname)
|
|
||||||
|
|
||||||
# to validate territory overlap
|
|
||||||
# make a map of territory: [list of names]
|
|
||||||
# if list against each territory has more than one element, raise exception
|
|
||||||
territory_name = frappe.db.sql("""select `territory`, `parent`
|
|
||||||
from `tabApplicable Territory`
|
|
||||||
where `parenttype`=%s and `parent` in (%s)""" %
|
|
||||||
("%s", ", ".join(["%s"]*len(names))), tuple([parenttype] + names))
|
|
||||||
|
|
||||||
for territory, name in territory_name:
|
|
||||||
territory_name_map.setdefault(territory, []).append(name)
|
|
||||||
|
|
||||||
if len(territory_name_map[territory]) > 1:
|
|
||||||
territory_name_map[territory].sort(key=lambda val: names.index(val))
|
|
||||||
|
|
||||||
return territory_name_map
|
|
||||||
|
|
||||||
def validate_exchange_rates_exist(self):
|
def validate_exchange_rates_exist(self):
|
||||||
"""check if exchange rates exist for all Price List currencies (to company's currency)"""
|
"""check if exchange rates exist for all Price List currencies (to company's currency)"""
|
||||||
company_currency = frappe.db.get_value("Company", self.company, "default_currency")
|
company_currency = frappe.db.get_value("Company", self.company, "default_currency")
|
||||||
@ -86,7 +27,7 @@ class ShoppingCartSettings(Document):
|
|||||||
raise_exception=ShoppingCartSetupError)
|
raise_exception=ShoppingCartSetupError)
|
||||||
|
|
||||||
price_list_currency_map = frappe.db.get_values("Price List",
|
price_list_currency_map = frappe.db.get_values("Price List",
|
||||||
[d.selling_price_list for d in self.get("price_lists")],
|
[self.price_list],
|
||||||
"currency")
|
"currency")
|
||||||
|
|
||||||
# check if all price lists have a currency
|
# check if all price lists have a currency
|
||||||
@ -109,28 +50,9 @@ class ShoppingCartSettings(Document):
|
|||||||
msgprint(_("Missing Currency Exchange Rates for {0}").format(comma_and(missing)),
|
msgprint(_("Missing Currency Exchange Rates for {0}").format(comma_and(missing)),
|
||||||
raise_exception=ShoppingCartSetupError)
|
raise_exception=ShoppingCartSetupError)
|
||||||
|
|
||||||
def get_name_from_territory(self, territory, parentfield, fieldname):
|
def validate_tax_rule(self):
|
||||||
name = None
|
if not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart" : 1}, "name"):
|
||||||
territory_name_map = self.get_territory_name_map(parentfield, fieldname)
|
frappe.throw(frappe._("Set Tax Rule for shopping cart"), ShoppingCartSetupError)
|
||||||
|
|
||||||
if territory_name_map.get(territory):
|
|
||||||
name = territory_name_map.get(territory)
|
|
||||||
else:
|
|
||||||
territory_ancestry = self.get_territory_ancestry(territory)
|
|
||||||
for ancestor in territory_ancestry:
|
|
||||||
if territory_name_map.get(ancestor):
|
|
||||||
name = territory_name_map.get(ancestor)
|
|
||||||
break
|
|
||||||
|
|
||||||
return name
|
|
||||||
|
|
||||||
def get_price_list(self, billing_territory):
|
|
||||||
price_list = self.get_name_from_territory(billing_territory, "price_lists", "selling_price_list")
|
|
||||||
if not (price_list and price_list[0]):
|
|
||||||
price_list = self.get_name_from_territory(self.default_territory or get_root_of("Territory"),
|
|
||||||
"price_lists", "selling_price_list")
|
|
||||||
|
|
||||||
return price_list and price_list[0] or None
|
|
||||||
|
|
||||||
def get_tax_master(self, billing_territory):
|
def get_tax_master(self, billing_territory):
|
||||||
tax_master = self.get_name_from_territory(billing_territory, "sales_taxes_and_charges_masters",
|
tax_master = self.get_name_from_territory(billing_territory, "sales_taxes_and_charges_masters",
|
||||||
@ -140,15 +62,6 @@ class ShoppingCartSettings(Document):
|
|||||||
def get_shipping_rules(self, shipping_territory):
|
def get_shipping_rules(self, shipping_territory):
|
||||||
return self.get_name_from_territory(shipping_territory, "shipping_rules", "shipping_rule")
|
return self.get_name_from_territory(shipping_territory, "shipping_rules", "shipping_rule")
|
||||||
|
|
||||||
def get_territory_ancestry(self, territory):
|
|
||||||
if not hasattr(self, "_territory_ancestry"):
|
|
||||||
self._territory_ancestry = {}
|
|
||||||
|
|
||||||
if not self._territory_ancestry.get(territory):
|
|
||||||
self._territory_ancestry[territory] = get_ancestors_of("Territory", territory)
|
|
||||||
|
|
||||||
return self._territory_ancestry[territory]
|
|
||||||
|
|
||||||
def validate_cart_settings(doc, method):
|
def validate_cart_settings(doc, method):
|
||||||
frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings").run_method("validate")
|
frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings").run_method("validate")
|
||||||
|
|
||||||
@ -161,58 +74,7 @@ def get_shopping_cart_settings():
|
|||||||
def is_cart_enabled():
|
def is_cart_enabled():
|
||||||
return get_shopping_cart_settings().enabled
|
return get_shopping_cart_settings().enabled
|
||||||
|
|
||||||
def get_default_territory():
|
|
||||||
return get_shopping_cart_settings().default_territory or get_root_of("Territory")
|
|
||||||
|
|
||||||
def check_shopping_cart_enabled():
|
def check_shopping_cart_enabled():
|
||||||
if not get_shopping_cart_settings().enabled:
|
if not get_shopping_cart_settings().enabled:
|
||||||
frappe.throw(_("You need to enable Shopping Cart"), ShoppingCartSetupError)
|
frappe.throw(_("You need to enable Shopping Cart"), ShoppingCartSetupError)
|
||||||
|
|
||||||
def apply_shopping_cart_settings(quotation, method):
|
|
||||||
"""Called via a validate hook on Quotation"""
|
|
||||||
from erpnext.shopping_cart import get_party
|
|
||||||
if quotation.order_type != "Shopping Cart":
|
|
||||||
return
|
|
||||||
|
|
||||||
quotation.billing_territory = (get_territory_from_address(quotation.customer_address)
|
|
||||||
or get_party(quotation.contact_email).territory or get_default_territory())
|
|
||||||
quotation.shipping_territory = (get_territory_from_address(quotation.shipping_address_name)
|
|
||||||
or get_party(quotation.contact_email).territory or get_default_territory())
|
|
||||||
|
|
||||||
set_price_list(quotation)
|
|
||||||
set_taxes_and_charges(quotation)
|
|
||||||
quotation.calculate_taxes_and_totals()
|
|
||||||
set_shipping_rule(quotation)
|
|
||||||
|
|
||||||
def set_price_list(quotation):
|
|
||||||
previous_selling_price_list = quotation.selling_price_list
|
|
||||||
quotation.selling_price_list = get_shopping_cart_settings().get_price_list(quotation.billing_territory)
|
|
||||||
|
|
||||||
if not quotation.selling_price_list:
|
|
||||||
quotation.selling_price_list = get_shopping_cart_settings().get_price_list(get_default_territory())
|
|
||||||
|
|
||||||
if previous_selling_price_list != quotation.selling_price_list:
|
|
||||||
quotation.price_list_currency = quotation.currency = quotation.plc_conversion_rate = quotation.conversion_rate = None
|
|
||||||
for d in quotation.get("items"):
|
|
||||||
d.price_list_rate = d.discount_percentage = d.rate = d.amount = None
|
|
||||||
|
|
||||||
quotation.set_price_list_and_item_details()
|
|
||||||
|
|
||||||
def set_taxes_and_charges(quotation):
|
|
||||||
previous_taxes_and_charges = quotation.taxes_and_charges
|
|
||||||
quotation.taxes_and_charges = get_shopping_cart_settings().get_tax_master(quotation.billing_territory)
|
|
||||||
|
|
||||||
if previous_taxes_and_charges != quotation.taxes_and_charges:
|
|
||||||
quotation.set_other_charges()
|
|
||||||
|
|
||||||
def set_shipping_rule(quotation):
|
|
||||||
shipping_rules = get_shopping_cart_settings().get_shipping_rules(quotation.shipping_territory)
|
|
||||||
if not shipping_rules:
|
|
||||||
quotation.remove_shipping_charge()
|
|
||||||
return
|
|
||||||
|
|
||||||
if quotation.shipping_rule not in shipping_rules:
|
|
||||||
quotation.remove_shipping_charge()
|
|
||||||
quotation.shipping_rule = shipping_rules[0]
|
|
||||||
|
|
||||||
quotation.apply_shipping_rule()
|
|
||||||
|
@ -11,69 +11,29 @@ from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings
|
|||||||
class TestShoppingCartSettings(unittest.TestCase):
|
class TestShoppingCartSettings(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
frappe.db.sql("""delete from `tabSingles` where doctype="Shipping Cart Settings" """)
|
frappe.db.sql("""delete from `tabSingles` where doctype="Shipping Cart Settings" """)
|
||||||
frappe.db.sql("""delete from `tabShopping Cart Price List`""")
|
|
||||||
frappe.db.sql("""delete from `tabShopping Cart Taxes and Charges Master`""")
|
|
||||||
frappe.db.sql("""delete from `tabShopping Cart Shipping Rule`""")
|
|
||||||
|
|
||||||
def get_cart_settings(self):
|
def get_cart_settings(self):
|
||||||
return frappe.get_doc({"doctype": "Shopping Cart Settings",
|
return frappe.get_doc({"doctype": "Shopping Cart Settings",
|
||||||
"company": "_Test Company"})
|
"company": "_Test Company"})
|
||||||
|
|
||||||
def test_price_list_territory_overlap(self):
|
|
||||||
cart_settings = self.get_cart_settings()
|
|
||||||
|
|
||||||
def _add_price_list(price_list):
|
|
||||||
cart_settings.append("price_lists", {
|
|
||||||
"doctype": "Shopping Cart Price List",
|
|
||||||
"selling_price_list": price_list
|
|
||||||
})
|
|
||||||
|
|
||||||
for price_list in ("_Test Price List Rest of the World", "_Test Price List India",
|
|
||||||
"_Test Price List"):
|
|
||||||
_add_price_list(price_list)
|
|
||||||
|
|
||||||
controller = cart_settings
|
|
||||||
controller.validate_overlapping_territories("price_lists", "selling_price_list")
|
|
||||||
|
|
||||||
_add_price_list("_Test Price List 2")
|
|
||||||
|
|
||||||
controller = cart_settings
|
|
||||||
self.assertRaises(ShoppingCartSetupError, controller.validate_overlapping_territories,
|
|
||||||
"price_lists", "selling_price_list")
|
|
||||||
|
|
||||||
return cart_settings
|
|
||||||
|
|
||||||
def test_taxes_territory_overlap(self):
|
|
||||||
cart_settings = self.get_cart_settings()
|
|
||||||
|
|
||||||
def _add_tax_master(tax_master):
|
|
||||||
cart_settings.append("sales_taxes_and_charges_masters", {
|
|
||||||
"doctype": "Shopping Cart Taxes and Charges Master",
|
|
||||||
"sales_taxes_and_charges_master": tax_master
|
|
||||||
})
|
|
||||||
|
|
||||||
for tax_master in ("_Test Sales Taxes and Charges Template", "_Test India Tax Master"):
|
|
||||||
_add_tax_master(tax_master)
|
|
||||||
|
|
||||||
controller = cart_settings
|
|
||||||
controller.validate_overlapping_territories("sales_taxes_and_charges_masters",
|
|
||||||
"sales_taxes_and_charges_master")
|
|
||||||
|
|
||||||
_add_tax_master("_Test Sales Taxes and Charges Template - Rest of the World")
|
|
||||||
|
|
||||||
controller = cart_settings
|
|
||||||
self.assertRaises(ShoppingCartSetupError, controller.validate_overlapping_territories,
|
|
||||||
"sales_taxes_and_charges_masters", "sales_taxes_and_charges_master")
|
|
||||||
|
|
||||||
def test_exchange_rate_exists(self):
|
def test_exchange_rate_exists(self):
|
||||||
frappe.db.sql("""delete from `tabCurrency Exchange`""")
|
frappe.db.sql("""delete from `tabCurrency Exchange`""")
|
||||||
|
|
||||||
cart_settings = self.test_price_list_territory_overlap()
|
cart_settings = self.get_cart_settings()
|
||||||
controller = cart_settings
|
cart_settings.price_list = "_Test Price List Rest of the World"
|
||||||
self.assertRaises(ShoppingCartSetupError, controller.validate_exchange_rates_exist)
|
self.assertRaises(ShoppingCartSetupError, cart_settings.validate_exchange_rates_exist)
|
||||||
|
|
||||||
from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records as \
|
from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records as \
|
||||||
currency_exchange_records
|
currency_exchange_records
|
||||||
frappe.get_doc(currency_exchange_records[0]).insert()
|
frappe.get_doc(currency_exchange_records[0]).insert()
|
||||||
controller.validate_exchange_rates_exist()
|
cart_settings.validate_exchange_rates_exist()
|
||||||
|
|
||||||
|
def test_tax_rule_validation(self):
|
||||||
|
frappe.db.sql("update `tabTax Rule` set use_for_shopping_cart = 0")
|
||||||
|
frappe.db.commit()
|
||||||
|
|
||||||
|
cart_settings = self.get_cart_settings()
|
||||||
|
cart_settings.enabled = 1
|
||||||
|
if not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart": 1}, "name"):
|
||||||
|
self.assertRaises(ShoppingCartSetupError, cart_settings.validate_tax_rule)
|
||||||
|
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# License: GNU General Public License v3. See license.txt
|
|
||||||
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
class ShoppingCartTaxesandChargesMaster(Document):
|
|
||||||
pass
|
|
@ -4,7 +4,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import unittest
|
import unittest
|
||||||
import frappe
|
import frappe
|
||||||
from erpnext.shopping_cart import get_quotation, set_item_in_cart
|
from erpnext.shopping_cart.cart import _get_cart_quotation, update_cart, get_customer
|
||||||
|
|
||||||
class TestShoppingCart(unittest.TestCase):
|
class TestShoppingCart(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
@ -23,23 +23,11 @@ class TestShoppingCart(unittest.TestCase):
|
|||||||
self.login_as_new_user()
|
self.login_as_new_user()
|
||||||
|
|
||||||
# test if lead is created and quotation with new lead is fetched
|
# test if lead is created and quotation with new lead is fetched
|
||||||
quotation = get_quotation()
|
quotation = _get_cart_quotation()
|
||||||
self.assertEquals(quotation.quotation_to, "Lead")
|
self.assertEquals(quotation.quotation_to, "Customer")
|
||||||
self.assertEquals(frappe.db.get_value("Lead", quotation.lead, "email_id"),
|
self.assertEquals(frappe.db.get_value("Contact", {"customer": quotation.customer}, "email_id"),
|
||||||
"test_cart_user@example.com")
|
"test_cart_user@example.com")
|
||||||
self.assertEquals(quotation.customer, None)
|
self.assertEquals(quotation.lead, None)
|
||||||
self.assertEquals(quotation.contact_email, frappe.session.user)
|
|
||||||
|
|
||||||
return quotation
|
|
||||||
|
|
||||||
def test_get_cart_lead(self):
|
|
||||||
self.login_as_lead()
|
|
||||||
|
|
||||||
# test if quotation with lead is fetched
|
|
||||||
quotation = get_quotation()
|
|
||||||
self.assertEquals(quotation.quotation_to, "Lead")
|
|
||||||
self.assertEquals(quotation.lead, frappe.db.get_value("Lead", {"email_id": "test_cart_lead@example.com"}))
|
|
||||||
self.assertEquals(quotation.customer, None)
|
|
||||||
self.assertEquals(quotation.contact_email, frappe.session.user)
|
self.assertEquals(quotation.contact_email, frappe.session.user)
|
||||||
|
|
||||||
return quotation
|
return quotation
|
||||||
@ -48,7 +36,7 @@ class TestShoppingCart(unittest.TestCase):
|
|||||||
self.login_as_customer()
|
self.login_as_customer()
|
||||||
|
|
||||||
# test if quotation with customer is fetched
|
# test if quotation with customer is fetched
|
||||||
quotation = get_quotation()
|
quotation = _get_cart_quotation()
|
||||||
self.assertEquals(quotation.quotation_to, "Customer")
|
self.assertEquals(quotation.quotation_to, "Customer")
|
||||||
self.assertEquals(quotation.customer, "_Test Customer")
|
self.assertEquals(quotation.customer, "_Test Customer")
|
||||||
self.assertEquals(quotation.lead, None)
|
self.assertEquals(quotation.lead, None)
|
||||||
@ -57,21 +45,24 @@ class TestShoppingCart(unittest.TestCase):
|
|||||||
return quotation
|
return quotation
|
||||||
|
|
||||||
def test_add_to_cart(self):
|
def test_add_to_cart(self):
|
||||||
self.login_as_lead()
|
self.login_as_customer()
|
||||||
|
|
||||||
# remove from cart
|
# remove from cart
|
||||||
self.remove_all_items_from_cart()
|
self.remove_all_items_from_cart()
|
||||||
|
|
||||||
# add first item
|
# add first item
|
||||||
set_item_in_cart("_Test Item", 1)
|
update_cart("_Test Item", 1)
|
||||||
quotation = self.test_get_cart_lead()
|
|
||||||
|
quotation = self.test_get_cart_customer()
|
||||||
|
|
||||||
self.assertEquals(quotation.get("items")[0].item_code, "_Test Item")
|
self.assertEquals(quotation.get("items")[0].item_code, "_Test Item")
|
||||||
self.assertEquals(quotation.get("items")[0].qty, 1)
|
self.assertEquals(quotation.get("items")[0].qty, 1)
|
||||||
self.assertEquals(quotation.get("items")[0].amount, 10)
|
self.assertEquals(quotation.get("items")[0].amount, 10)
|
||||||
|
|
||||||
|
|
||||||
# add second item
|
# add second item
|
||||||
set_item_in_cart("_Test Item 2", 1)
|
update_cart("_Test Item 2", 1)
|
||||||
quotation = self.test_get_cart_lead()
|
quotation = self.test_get_cart_customer()
|
||||||
self.assertEquals(quotation.get("items")[1].item_code, "_Test Item 2")
|
self.assertEquals(quotation.get("items")[1].item_code, "_Test Item 2")
|
||||||
self.assertEquals(quotation.get("items")[1].qty, 1)
|
self.assertEquals(quotation.get("items")[1].qty, 1)
|
||||||
self.assertEquals(quotation.get("items")[1].amount, 20)
|
self.assertEquals(quotation.get("items")[1].amount, 20)
|
||||||
@ -83,8 +74,8 @@ class TestShoppingCart(unittest.TestCase):
|
|||||||
self.test_add_to_cart()
|
self.test_add_to_cart()
|
||||||
|
|
||||||
# update first item
|
# update first item
|
||||||
set_item_in_cart("_Test Item", 5)
|
update_cart("_Test Item", 5)
|
||||||
quotation = self.test_get_cart_lead()
|
quotation = self.test_get_cart_customer()
|
||||||
self.assertEquals(quotation.get("items")[0].item_code, "_Test Item")
|
self.assertEquals(quotation.get("items")[0].item_code, "_Test Item")
|
||||||
self.assertEquals(quotation.get("items")[0].qty, 5)
|
self.assertEquals(quotation.get("items")[0].qty, 5)
|
||||||
self.assertEquals(quotation.get("items")[0].amount, 50)
|
self.assertEquals(quotation.get("items")[0].amount, 50)
|
||||||
@ -96,8 +87,9 @@ class TestShoppingCart(unittest.TestCase):
|
|||||||
self.test_add_to_cart()
|
self.test_add_to_cart()
|
||||||
|
|
||||||
# remove first item
|
# remove first item
|
||||||
set_item_in_cart("_Test Item", 0)
|
update_cart("_Test Item", 0)
|
||||||
quotation = self.test_get_cart_lead()
|
quotation = self.test_get_cart_customer()
|
||||||
|
|
||||||
self.assertEquals(quotation.get("items")[0].item_code, "_Test Item 2")
|
self.assertEquals(quotation.get("items")[0].item_code, "_Test Item 2")
|
||||||
self.assertEquals(quotation.get("items")[0].qty, 1)
|
self.assertEquals(quotation.get("items")[0].qty, 1)
|
||||||
self.assertEquals(quotation.get("items")[0].amount, 20)
|
self.assertEquals(quotation.get("items")[0].amount, 20)
|
||||||
@ -105,41 +97,85 @@ class TestShoppingCart(unittest.TestCase):
|
|||||||
self.assertEquals(len(quotation.get("items")), 1)
|
self.assertEquals(len(quotation.get("items")), 1)
|
||||||
|
|
||||||
# remove second item
|
# remove second item
|
||||||
set_item_in_cart("_Test Item 2", 0)
|
update_cart("_Test Item 2", 0)
|
||||||
quotation = self.test_get_cart_lead()
|
quotation = self.test_get_cart_customer()
|
||||||
self.assertEquals(quotation.net_total, 0)
|
|
||||||
self.assertEquals(len(quotation.get("items")), 0)
|
self.assertEquals(len(quotation.get("items")), 0)
|
||||||
|
self.assertEquals(quotation.net_total, 0)
|
||||||
|
|
||||||
|
def test_tax_rule(self):
|
||||||
|
self.login_as_customer()
|
||||||
|
quotation = self.create_quotation()
|
||||||
|
|
||||||
|
from erpnext.accounts.party import set_taxes
|
||||||
|
|
||||||
|
tax_rule_master = set_taxes(quotation.customer, "Customer", \
|
||||||
|
quotation.transaction_date, quotation.company, None, None, \
|
||||||
|
quotation.customer_address, quotation.shipping_address_name, 1)
|
||||||
|
|
||||||
|
self.assertEquals(quotation.taxes_and_charges, tax_rule_master)
|
||||||
|
self.assertEquals(quotation.total_taxes_and_charges, 1000.0)
|
||||||
|
|
||||||
|
self.remove_test_quotation(quotation)
|
||||||
|
|
||||||
|
def create_quotation(self):
|
||||||
|
quotation = frappe.new_doc("Quotation")
|
||||||
|
|
||||||
|
values = {
|
||||||
|
"doctype": "Quotation",
|
||||||
|
"quotation_to": "Customer",
|
||||||
|
"order_type": "Shopping Cart",
|
||||||
|
"customer": get_customer(frappe.session.user).name,
|
||||||
|
"docstatus": 0,
|
||||||
|
"contact_email": frappe.session.user,
|
||||||
|
"selling_price_list": "_Test Price List Rest of the World",
|
||||||
|
"currency": "USD",
|
||||||
|
"taxes_and_charges" : "_Test Tax 1",
|
||||||
|
"items": [{
|
||||||
|
"item_code": "_Test Item",
|
||||||
|
"qty": 1
|
||||||
|
}],
|
||||||
|
"taxes": frappe.get_doc("Sales Taxes and Charges Template", "_Test Tax 1").taxes,
|
||||||
|
"company": "_Test Company"
|
||||||
|
}
|
||||||
|
|
||||||
|
quotation.update(values)
|
||||||
|
|
||||||
|
quotation.insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
return quotation
|
||||||
|
|
||||||
|
def remove_test_quotation(self, quotation):
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
quotation.delete()
|
||||||
|
|
||||||
# helper functions
|
# helper functions
|
||||||
def enable_shopping_cart(self):
|
def enable_shopping_cart(self):
|
||||||
settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings")
|
settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings")
|
||||||
|
|
||||||
if settings.get("price_lists"):
|
settings.update({
|
||||||
settings.enabled = 1
|
"enabled": 1,
|
||||||
else:
|
"company": "_Test Company",
|
||||||
settings.update({
|
"default_customer_group": "_Test Customer Group",
|
||||||
"enabled": 1,
|
"quotation_series": "_T-Quotation-",
|
||||||
"company": "_Test Company",
|
"price_list": "_Test Price List India"
|
||||||
"default_territory": "_Test Territory Rest Of The World",
|
})
|
||||||
"default_customer_group": "_Test Customer Group",
|
|
||||||
"quotation_series": "_T-Quotation-"
|
# insert item price
|
||||||
})
|
if not frappe.db.get_value("Item Price", {"price_list": "_Test Price List India",
|
||||||
settings.set("price_lists", [
|
"item_code": "_Test Item"}):
|
||||||
# price lists
|
frappe.get_doc({
|
||||||
{"doctype": "Shopping Cart Price List", "parentfield": "price_lists",
|
"doctype": "Item Price",
|
||||||
"selling_price_list": "_Test Price List India"},
|
"price_list": "_Test Price List India",
|
||||||
{"doctype": "Shopping Cart Price List", "parentfield": "price_lists",
|
"item_code": "_Test Item",
|
||||||
"selling_price_list": "_Test Price List Rest of the World"}
|
"price_list_rate": 10
|
||||||
])
|
}).insert()
|
||||||
settings.set("sales_taxes_and_charges_masters", [
|
frappe.get_doc({
|
||||||
# tax masters
|
"doctype": "Item Price",
|
||||||
{"doctype": "Shopping Cart Taxes and Charges Master", "parentfield": "sales_taxes_and_charges_masters",
|
"price_list": "_Test Price List India",
|
||||||
"sales_taxes_and_charges_master": "_Test India Tax Master"},
|
"item_code": "_Test Item 2",
|
||||||
{"doctype": "Shopping Cart Taxes and Charges Master", "parentfield": "sales_taxes_and_charges_masters",
|
"price_list_rate": 20
|
||||||
"sales_taxes_and_charges_master": "_Test Sales Taxes and Charges Template - Rest of the World"},
|
}).insert()
|
||||||
])
|
|
||||||
settings.set("shipping_rules", {"doctype": "Shopping Cart Shipping Rule", "parentfield": "shipping_rules",
|
|
||||||
"shipping_rule": "_Test Shipping Rule - India"})
|
|
||||||
|
|
||||||
settings.save()
|
settings.save()
|
||||||
frappe.local.shopping_cart_settings = None
|
frappe.local.shopping_cart_settings = None
|
||||||
@ -153,57 +189,13 @@ class TestShoppingCart(unittest.TestCase):
|
|||||||
def login_as_new_user(self):
|
def login_as_new_user(self):
|
||||||
frappe.set_user("test_cart_user@example.com")
|
frappe.set_user("test_cart_user@example.com")
|
||||||
|
|
||||||
def login_as_lead(self):
|
|
||||||
self.create_lead()
|
|
||||||
frappe.set_user("test_cart_lead@example.com")
|
|
||||||
|
|
||||||
def login_as_customer(self):
|
def login_as_customer(self):
|
||||||
frappe.set_user("test_contact_customer@example.com")
|
frappe.set_user("test_contact_customer@example.com")
|
||||||
|
|
||||||
def create_lead(self):
|
|
||||||
if frappe.db.get_value("Lead", {"email_id": "test_cart_lead@example.com"}):
|
|
||||||
return
|
|
||||||
|
|
||||||
lead = frappe.get_doc({
|
|
||||||
"doctype": "Lead",
|
|
||||||
"email_id": "test_cart_lead@example.com",
|
|
||||||
"lead_name": "_Test Website Lead",
|
|
||||||
"status": "Open",
|
|
||||||
"territory": "_Test Territory Rest Of The World",
|
|
||||||
"company": "_Test Company"
|
|
||||||
})
|
|
||||||
lead.insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
frappe.get_doc({
|
|
||||||
"doctype": "Address",
|
|
||||||
"address_line1": "_Test Address Line 1",
|
|
||||||
"address_title": "_Test Cart Lead Address",
|
|
||||||
"address_type": "Office",
|
|
||||||
"city": "_Test City",
|
|
||||||
"country": "United States",
|
|
||||||
"lead": lead.name,
|
|
||||||
"lead_name": "_Test Website Lead",
|
|
||||||
"is_primary_address": 1,
|
|
||||||
"phone": "+91 0000000000"
|
|
||||||
}).insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
frappe.get_doc({
|
|
||||||
"doctype": "Address",
|
|
||||||
"address_line1": "_Test Address Line 1",
|
|
||||||
"address_title": "_Test Cart Lead Address",
|
|
||||||
"address_type": "Personal",
|
|
||||||
"city": "_Test City",
|
|
||||||
"country": "India",
|
|
||||||
"lead": lead.name,
|
|
||||||
"lead_name": "_Test Website Lead",
|
|
||||||
"phone": "+91 0000000000"
|
|
||||||
}).insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
def remove_all_items_from_cart(self):
|
def remove_all_items_from_cart(self):
|
||||||
quotation = get_quotation()
|
quotation = _get_cart_quotation()
|
||||||
quotation.set("items", [])
|
quotation.set("items", [])
|
||||||
quotation.save(ignore_permissions=True)
|
quotation.save(ignore_permissions=True)
|
||||||
|
|
||||||
|
|
||||||
test_dependencies = ["Sales Taxes and Charges Template", "Price List", "Item Price", "Shipping Rule", "Currency Exchange",
|
test_dependencies = ["Sales Taxes and Charges Template", "Price List", "Item Price", "Shipping Rule", "Currency Exchange",
|
||||||
"Customer Group", "Lead", "Customer", "Contact", "Address", "Item"]
|
"Customer Group", "Lead", "Customer", "Contact", "Address", "Item", "Tax Rule"]
|
||||||
|
@ -2405,7 +2405,7 @@
|
|||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"fieldname": "sales_team",
|
"fieldname": "sales_team",
|
||||||
@ -2438,7 +2438,7 @@
|
|||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-09-11 12:20:00.264753",
|
"modified": "2015-09-23 09:54:33.751001",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Delivery Note",
|
"name": "Delivery Note",
|
||||||
|
@ -19,6 +19,7 @@ class Item(WebsiteGenerator):
|
|||||||
condition_field = "show_in_website",
|
condition_field = "show_in_website",
|
||||||
template = "templates/generators/item.html",
|
template = "templates/generators/item.html",
|
||||||
parent_website_route_field = "item_group",
|
parent_website_route_field = "item_group",
|
||||||
|
no_cache = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
def onload(self):
|
def onload(self):
|
||||||
|
@ -3,9 +3,9 @@ frappe.listview_settings['Material Request'] = {
|
|||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if(doc.status=="Stopped") {
|
if(doc.status=="Stopped") {
|
||||||
return [__("Stopped"), "red", "status,=,Stopped"];
|
return [__("Stopped"), "red", "status,=,Stopped"];
|
||||||
} else if(doc.docstatus==1 && flt(doc.per_ordered) < 100) {
|
} else if(doc.docstatus==1 && flt(doc.per_ordered, 2) < 100) {
|
||||||
return [__("Pending"), "orange", "per_ordered,<,100"];
|
return [__("Pending"), "orange", "per_ordered,<,100"];
|
||||||
} else if(doc.docstatus==1 && flt(doc.per_ordered) == 100) {
|
} else if(doc.docstatus==1 && flt(doc.per_ordered, 2) == 100) {
|
||||||
if (doc.material_request_type == "Purchase") {
|
if (doc.material_request_type == "Purchase") {
|
||||||
return [__("Ordered"), "green", "per_ordered,=,100"];
|
return [__("Ordered"), "green", "per_ordered,=,100"];
|
||||||
} else if (doc.material_request_type == "Material Transfer") {
|
} else if (doc.material_request_type == "Material Transfer") {
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
$.extend(cur_frm.cscript, {
|
$.extend(cur_frm.cscript, {
|
||||||
onload: function() {
|
|
||||||
erpnext.add_applicable_territory();
|
|
||||||
},
|
|
||||||
|
|
||||||
refresh: function() {
|
refresh: function() {
|
||||||
cur_frm.add_custom_button(__("Add / Edit Prices"), function() {
|
cur_frm.add_custom_button(__("Add / Edit Prices"), function() {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
@ -14,4 +10,4 @@ $.extend(cur_frm.cscript, {
|
|||||||
frappe.set_route("Report", "Item Price");
|
frappe.set_route("Report", "Item Price");
|
||||||
}, "icon-money");
|
}, "icon-money");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -163,21 +163,21 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"description": "Specify a list of Territories, for which, this Price List is valid",
|
"fieldname": "countries",
|
||||||
"fieldname": "territories",
|
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Valid for Territories",
|
"label": "Applicable for Countries",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Applicable Territory",
|
"options": "Price List Country",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
@ -193,7 +193,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 1,
|
"max_attachments": 1,
|
||||||
"modified": "2015-09-14 02:55:58.919822",
|
"modified": "2015-09-17 06:50:31.465221",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Price List",
|
"name": "Price List",
|
||||||
@ -201,7 +201,7 @@
|
|||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
"apply_user_permissions": 1,
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"delete": 0,
|
"delete": 0,
|
||||||
@ -241,7 +241,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
"apply_user_permissions": 1,
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"delete": 0,
|
"delete": 0,
|
||||||
@ -281,7 +281,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"amend": 0,
|
||||||
"apply_user_permissions": 0,
|
"apply_user_permissions": 1,
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 0,
|
"create": 0,
|
||||||
"delete": 0,
|
"delete": 0,
|
||||||
|
@ -13,19 +13,6 @@ class PriceList(Document):
|
|||||||
if not cint(self.buying) and not cint(self.selling):
|
if not cint(self.buying) and not cint(self.selling):
|
||||||
throw(_("Price List must be applicable for Buying or Selling"))
|
throw(_("Price List must be applicable for Buying or Selling"))
|
||||||
|
|
||||||
try:
|
|
||||||
# at least one territory
|
|
||||||
self.validate_table_has_rows("territories")
|
|
||||||
except frappe.EmptyTableError:
|
|
||||||
# if no territory, set default territory
|
|
||||||
if frappe.defaults.get_user_default("territory"):
|
|
||||||
self.append("territories", {
|
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"territory": frappe.defaults.get_user_default("territory")
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
self.set_default_if_missing()
|
self.set_default_if_missing()
|
||||||
self.update_item_price()
|
self.update_item_price()
|
||||||
|
@ -1,67 +1,34 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"buying": 1,
|
"buying": 1,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"doctype": "Price List",
|
"doctype": "Price List",
|
||||||
"enabled": 1,
|
"enabled": 1,
|
||||||
"price_list_name": "_Test Price List",
|
"price_list_name": "_Test Price List",
|
||||||
"selling": 1,
|
"selling": 1
|
||||||
"territories": [
|
},
|
||||||
{
|
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"parentfield": "territories",
|
|
||||||
"territory": "All Territories"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"buying": 1,
|
"buying": 1,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"doctype": "Price List",
|
"doctype": "Price List",
|
||||||
"enabled": 1,
|
"enabled": 1,
|
||||||
"price_list_name": "_Test Price List 2",
|
"price_list_name": "_Test Price List 2",
|
||||||
"selling": 1,
|
"selling": 1
|
||||||
"territories": [
|
},
|
||||||
{
|
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"parentfield": "territories",
|
|
||||||
"territory": "_Test Territory Rest Of The World"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"buying": 1,
|
"buying": 1,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"doctype": "Price List",
|
"doctype": "Price List",
|
||||||
"enabled": 1,
|
"enabled": 1,
|
||||||
"price_list_name": "_Test Price List India",
|
"price_list_name": "_Test Price List India",
|
||||||
"selling": 1,
|
"selling": 1
|
||||||
"territories": [
|
},
|
||||||
{
|
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"parentfield": "territories",
|
|
||||||
"territory": "_Test Territory India"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"buying": 1,
|
"buying": 1,
|
||||||
"currency": "USD",
|
"currency": "USD",
|
||||||
"doctype": "Price List",
|
"doctype": "Price List",
|
||||||
"enabled": 1,
|
"enabled": 1,
|
||||||
"price_list_name": "_Test Price List Rest of the World",
|
"price_list_name": "_Test Price List Rest of the World",
|
||||||
"selling": 1,
|
"selling": 1
|
||||||
"territories": [
|
|
||||||
{
|
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"parentfield": "territories",
|
|
||||||
"territory": "_Test Territory Rest Of The World"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"doctype": "Applicable Territory",
|
|
||||||
"parentfield": "territories",
|
|
||||||
"territory": "_Test Territory United States"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2,26 +2,27 @@
|
|||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"creation": "2013-06-20 12:48:38",
|
"creation": "2015-09-17 06:49:51.810318",
|
||||||
"custom": 0,
|
"custom": 0,
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
|
"document_type": "",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"description": "",
|
"fieldname": "country",
|
||||||
"fieldname": "territory",
|
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Territory",
|
"label": "Country",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Territory",
|
"options": "Country",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
@ -33,18 +34,20 @@
|
|||||||
],
|
],
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
"hide_toolbar": 0,
|
"hide_toolbar": 0,
|
||||||
"idx": 1,
|
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"in_dialog": 0,
|
"in_dialog": 0,
|
||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2015-01-01 14:29:58.724652",
|
"modified": "2015-09-17 06:49:51.810318",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Stock",
|
||||||
"name": "Applicable Territory",
|
"name": "Price List Country",
|
||||||
|
"name_case": "",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0
|
"read_only_onload": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC"
|
||||||
}
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class PriceListCountry(Document):
|
||||||
|
pass
|
@ -49,7 +49,7 @@ class StockEntry(StockController):
|
|||||||
self.validate_finished_goods()
|
self.validate_finished_goods()
|
||||||
self.validate_with_material_request()
|
self.validate_with_material_request()
|
||||||
self.validate_batch()
|
self.validate_batch()
|
||||||
|
|
||||||
self.set_actual_qty()
|
self.set_actual_qty()
|
||||||
self.calculate_rate_and_amount()
|
self.calculate_rate_and_amount()
|
||||||
|
|
||||||
@ -212,10 +212,10 @@ class StockEntry(StockController):
|
|||||||
if fg_qty_already_entered >= qty:
|
if fg_qty_already_entered >= qty:
|
||||||
frappe.throw(_("Stock Entries already created for Production Order ")
|
frappe.throw(_("Stock Entries already created for Production Order ")
|
||||||
+ self.production_order + ":" + ", ".join(other_ste), DuplicateEntryForProductionOrderError)
|
+ self.production_order + ":" + ", ".join(other_ste), DuplicateEntryForProductionOrderError)
|
||||||
|
|
||||||
def set_actual_qty(self):
|
def set_actual_qty(self):
|
||||||
allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock"))
|
allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock"))
|
||||||
|
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
previous_sle = get_previous_sle({
|
previous_sle = get_previous_sle({
|
||||||
"item_code": d.item_code,
|
"item_code": d.item_code,
|
||||||
@ -232,7 +232,7 @@ class StockEntry(StockController):
|
|||||||
frappe.throw(_("""Row {0}: Qty not avalable in warehouse {1} on {2} {3}.
|
frappe.throw(_("""Row {0}: Qty not avalable in warehouse {1} on {2} {3}.
|
||||||
Available Qty: {4}, Transfer Qty: {5}""").format(d.idx, d.s_warehouse,
|
Available Qty: {4}, Transfer Qty: {5}""").format(d.idx, d.s_warehouse,
|
||||||
self.posting_date, self.posting_time, d.actual_qty, d.transfer_qty), NegativeStockError)
|
self.posting_date, self.posting_time, d.actual_qty, d.transfer_qty), NegativeStockError)
|
||||||
|
|
||||||
def get_stock_and_rate(self):
|
def get_stock_and_rate(self):
|
||||||
self.set_actual_qty()
|
self.set_actual_qty()
|
||||||
self.calculate_rate_and_amount()
|
self.calculate_rate_and_amount()
|
||||||
@ -244,7 +244,7 @@ class StockEntry(StockController):
|
|||||||
self.validate_valuation_rate()
|
self.validate_valuation_rate()
|
||||||
self.set_total_incoming_outgoing_value()
|
self.set_total_incoming_outgoing_value()
|
||||||
self.set_total_amount()
|
self.set_total_amount()
|
||||||
|
|
||||||
def set_basic_rate(self, force=False):
|
def set_basic_rate(self, force=False):
|
||||||
"""get stock and incoming rate on posting date"""
|
"""get stock and incoming rate on posting date"""
|
||||||
raw_material_cost = 0.0
|
raw_material_cost = 0.0
|
||||||
@ -269,9 +269,9 @@ class StockEntry(StockController):
|
|||||||
d.basic_amount = flt(flt(d.transfer_qty) * flt(d.basic_rate), d.precision("basic_amount"))
|
d.basic_amount = flt(flt(d.transfer_qty) * flt(d.basic_rate), d.precision("basic_amount"))
|
||||||
if not d.t_warehouse:
|
if not d.t_warehouse:
|
||||||
raw_material_cost += flt(d.basic_amount)
|
raw_material_cost += flt(d.basic_amount)
|
||||||
|
|
||||||
self.set_basic_rate_for_finished_goods(raw_material_cost)
|
self.set_basic_rate_for_finished_goods(raw_material_cost)
|
||||||
|
|
||||||
def set_basic_rate_for_finished_goods(self, raw_material_cost):
|
def set_basic_rate_for_finished_goods(self, raw_material_cost):
|
||||||
if self.purpose in ["Manufacture", "Repack"]:
|
if self.purpose in ["Manufacture", "Repack"]:
|
||||||
number_of_fg_items = len([t.t_warehouse for t in self.get("items") if t.t_warehouse])
|
number_of_fg_items = len([t.t_warehouse for t in self.get("items") if t.t_warehouse])
|
||||||
@ -279,11 +279,11 @@ class StockEntry(StockController):
|
|||||||
if d.bom_no or (d.t_warehouse and number_of_fg_items == 1):
|
if d.bom_no or (d.t_warehouse and number_of_fg_items == 1):
|
||||||
d.basic_rate = flt(raw_material_cost / flt(d.transfer_qty), d.precision("basic_rate"))
|
d.basic_rate = flt(raw_material_cost / flt(d.transfer_qty), d.precision("basic_rate"))
|
||||||
d.basic_amount = flt(raw_material_cost, d.precision("basic_amount"))
|
d.basic_amount = flt(raw_material_cost, d.precision("basic_amount"))
|
||||||
|
|
||||||
def distribute_additional_costs(self):
|
def distribute_additional_costs(self):
|
||||||
if self.purpose == "Material Issue":
|
if self.purpose == "Material Issue":
|
||||||
self.additional_costs = []
|
self.additional_costs = []
|
||||||
|
|
||||||
self.total_additional_costs = sum([flt(t.amount) for t in self.get("additional_costs")])
|
self.total_additional_costs = sum([flt(t.amount) for t in self.get("additional_costs")])
|
||||||
total_basic_amount = sum([flt(t.basic_amount) for t in self.get("items") if t.t_warehouse])
|
total_basic_amount = sum([flt(t.basic_amount) for t in self.get("items") if t.t_warehouse])
|
||||||
|
|
||||||
@ -292,11 +292,11 @@ class StockEntry(StockController):
|
|||||||
d.additional_cost = (flt(d.basic_amount) / total_basic_amount) * self.total_additional_costs
|
d.additional_cost = (flt(d.basic_amount) / total_basic_amount) * self.total_additional_costs
|
||||||
else:
|
else:
|
||||||
d.additional_cost = 0
|
d.additional_cost = 0
|
||||||
|
|
||||||
def update_valuation_rate(self):
|
def update_valuation_rate(self):
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
d.amount = flt(d.basic_amount + flt(d.additional_cost), d.precision("amount"))
|
d.amount = flt(d.basic_amount + flt(d.additional_cost), d.precision("amount"))
|
||||||
d.valuation_rate = flt(flt(d.basic_rate) + flt(d.additional_cost) / flt(d.transfer_qty),
|
d.valuation_rate = flt(flt(d.basic_rate) + flt(d.additional_cost) / flt(d.transfer_qty),
|
||||||
d.precision("valuation_rate"))
|
d.precision("valuation_rate"))
|
||||||
|
|
||||||
def validate_valuation_rate(self):
|
def validate_valuation_rate(self):
|
||||||
@ -373,7 +373,7 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
def update_stock_ledger(self):
|
def update_stock_ledger(self):
|
||||||
sl_entries = []
|
sl_entries = []
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if cstr(d.s_warehouse) and self.docstatus == 1:
|
if cstr(d.s_warehouse) and self.docstatus == 1:
|
||||||
sl_entries.append(self.get_sl_entries(d, {
|
sl_entries.append(self.get_sl_entries(d, {
|
||||||
"warehouse": cstr(d.s_warehouse),
|
"warehouse": cstr(d.s_warehouse),
|
||||||
@ -399,15 +399,15 @@ class StockEntry(StockController):
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
self.make_sl_entries(sl_entries, self.amended_from and 'Yes' or 'No')
|
self.make_sl_entries(sl_entries, self.amended_from and 'Yes' or 'No')
|
||||||
|
|
||||||
def get_gl_entries(self, warehouse_account):
|
def get_gl_entries(self, warehouse_account):
|
||||||
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
|
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
|
||||||
|
|
||||||
gl_entries = super(StockEntry, self).get_gl_entries(warehouse_account)
|
gl_entries = super(StockEntry, self).get_gl_entries(warehouse_account)
|
||||||
|
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
additional_cost = flt(d.additional_cost, d.precision("additional_cost"))
|
additional_cost = flt(d.additional_cost, d.precision("additional_cost"))
|
||||||
if additional_cost:
|
if additional_cost:
|
||||||
gl_entries.append(self.get_gl_dict({
|
gl_entries.append(self.get_gl_dict({
|
||||||
"account": expenses_included_in_valuation,
|
"account": expenses_included_in_valuation,
|
||||||
"against": d.expense_account,
|
"against": d.expense_account,
|
||||||
@ -415,7 +415,7 @@ class StockEntry(StockController):
|
|||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
"credit": additional_cost
|
"credit": additional_cost
|
||||||
}))
|
}))
|
||||||
|
|
||||||
gl_entries.append(self.get_gl_dict({
|
gl_entries.append(self.get_gl_dict({
|
||||||
"account": d.expense_account,
|
"account": d.expense_account,
|
||||||
"against": expenses_included_in_valuation,
|
"against": expenses_included_in_valuation,
|
||||||
@ -521,7 +521,7 @@ class StockEntry(StockController):
|
|||||||
def get_items(self):
|
def get_items(self):
|
||||||
self.set('items', [])
|
self.set('items', [])
|
||||||
self.validate_production_order()
|
self.validate_production_order()
|
||||||
|
|
||||||
if not self.posting_date or not self.posting_time:
|
if not self.posting_date or not self.posting_time:
|
||||||
frappe.throw(_("Posting date and posting time is mandatory"))
|
frappe.throw(_("Posting date and posting time is mandatory"))
|
||||||
|
|
||||||
@ -548,7 +548,7 @@ class StockEntry(StockController):
|
|||||||
for item in item_dict.values():
|
for item in item_dict.values():
|
||||||
item["to_warehouse"] = self.pro_doc.wip_warehouse
|
item["to_warehouse"] = self.pro_doc.wip_warehouse
|
||||||
self.add_to_stock_entry_detail(item_dict)
|
self.add_to_stock_entry_detail(item_dict)
|
||||||
|
|
||||||
elif self.production_order and self.purpose == "Manufacture" and \
|
elif self.production_order and self.purpose == "Manufacture" and \
|
||||||
frappe.db.get_single_value("Manufacturing Settings", "backflush_raw_materials_based_on")== "Material Transferred for Manufacture":
|
frappe.db.get_single_value("Manufacturing Settings", "backflush_raw_materials_based_on")== "Material Transferred for Manufacture":
|
||||||
self.get_transfered_raw_materials()
|
self.get_transfered_raw_materials()
|
||||||
@ -578,10 +578,14 @@ class StockEntry(StockController):
|
|||||||
to_warehouse = self.pro_doc.fg_warehouse
|
to_warehouse = self.pro_doc.fg_warehouse
|
||||||
else:
|
else:
|
||||||
item_code = frappe.db.get_value("BOM", self.bom_no, "item")
|
item_code = frappe.db.get_value("BOM", self.bom_no, "item")
|
||||||
to_warehouse = ""
|
to_warehouse = self.to_warehouse
|
||||||
|
|
||||||
item = frappe.db.get_value("Item", item_code, ["item_name",
|
item = frappe.db.get_value("Item", item_code, ["item_name",
|
||||||
"description", "stock_uom", "expense_account", "buying_cost_center", "name"], as_dict=1)
|
"description", "stock_uom", "expense_account", "buying_cost_center", "name", "default_warehouse"], as_dict=1)
|
||||||
|
|
||||||
|
if not self.production_order and not to_warehouse:
|
||||||
|
# in case of BOM
|
||||||
|
to_warehouse = item.default_warehouse
|
||||||
|
|
||||||
self.add_to_stock_entry_detail({
|
self.add_to_stock_entry_detail({
|
||||||
item.name: {
|
item.name: {
|
||||||
@ -600,57 +604,57 @@ class StockEntry(StockController):
|
|||||||
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||||
|
|
||||||
# item dict = { item_code: {qty, description, stock_uom} }
|
# item dict = { item_code: {qty, description, stock_uom} }
|
||||||
item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=qty,
|
item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=qty,
|
||||||
fetch_exploded = self.use_multi_level_bom)
|
fetch_exploded = self.use_multi_level_bom)
|
||||||
|
|
||||||
for item in item_dict.values():
|
for item in item_dict.values():
|
||||||
item.from_warehouse = self.from_warehouse or item.default_warehouse
|
item.from_warehouse = self.from_warehouse or item.default_warehouse
|
||||||
return item_dict
|
return item_dict
|
||||||
|
|
||||||
def get_transfered_raw_materials(self):
|
def get_transfered_raw_materials(self):
|
||||||
transferred_materials = frappe.db.sql("""
|
transferred_materials = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
item_name, item_code, sum(qty) as qty, sed.t_warehouse as warehouse,
|
item_name, item_code, sum(qty) as qty, sed.t_warehouse as warehouse,
|
||||||
description, stock_uom, expense_account, cost_center
|
description, stock_uom, expense_account, cost_center
|
||||||
from `tabStock Entry` se,`tabStock Entry Detail` sed
|
from `tabStock Entry` se,`tabStock Entry Detail` sed
|
||||||
where
|
where
|
||||||
se.name = sed.parent and se.docstatus=1 and se.purpose='Material Transfer for Manufacture'
|
se.name = sed.parent and se.docstatus=1 and se.purpose='Material Transfer for Manufacture'
|
||||||
and se.production_order= %s and ifnull(sed.t_warehouse, '') != ''
|
and se.production_order= %s and ifnull(sed.t_warehouse, '') != ''
|
||||||
group by sed.item_code, sed.t_warehouse
|
group by sed.item_code, sed.t_warehouse
|
||||||
""", self.production_order, as_dict=1)
|
""", self.production_order, as_dict=1)
|
||||||
|
|
||||||
materials_already_backflushed = frappe.db.sql("""
|
materials_already_backflushed = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
item_code, sed.s_warehouse as warehouse, sum(qty) as qty
|
item_code, sed.s_warehouse as warehouse, sum(qty) as qty
|
||||||
from
|
from
|
||||||
`tabStock Entry` se, `tabStock Entry Detail` sed
|
`tabStock Entry` se, `tabStock Entry Detail` sed
|
||||||
where
|
where
|
||||||
se.name = sed.parent and se.docstatus=1 and se.purpose='Manufacture'
|
se.name = sed.parent and se.docstatus=1 and se.purpose='Manufacture'
|
||||||
and se.production_order= %s and ifnull(sed.s_warehouse, '') != ''
|
and se.production_order= %s and ifnull(sed.s_warehouse, '') != ''
|
||||||
group by sed.item_code, sed.s_warehouse
|
group by sed.item_code, sed.s_warehouse
|
||||||
""", self.production_order, as_dict=1)
|
""", self.production_order, as_dict=1)
|
||||||
|
|
||||||
backflushed_materials= {}
|
backflushed_materials= {}
|
||||||
for d in materials_already_backflushed:
|
for d in materials_already_backflushed:
|
||||||
backflushed_materials.setdefault(d.item_code,[]).append({d.warehouse: d.qty})
|
backflushed_materials.setdefault(d.item_code,[]).append({d.warehouse: d.qty})
|
||||||
|
|
||||||
po_qty = frappe.db.sql("""select qty, produced_qty, material_transferred_for_manufacturing from
|
po_qty = frappe.db.sql("""select qty, produced_qty, material_transferred_for_manufacturing from
|
||||||
`tabProduction Order` where name=%s""", self.production_order, as_dict=1)[0]
|
`tabProduction Order` where name=%s""", self.production_order, as_dict=1)[0]
|
||||||
manufacturing_qty = flt(po_qty.qty)
|
manufacturing_qty = flt(po_qty.qty)
|
||||||
produced_qty = flt(po_qty.produced_qty)
|
produced_qty = flt(po_qty.produced_qty)
|
||||||
trans_qty = flt(po_qty.material_transferred_for_manufacturing)
|
trans_qty = flt(po_qty.material_transferred_for_manufacturing)
|
||||||
|
|
||||||
for item in transferred_materials:
|
for item in transferred_materials:
|
||||||
qty= item.qty
|
qty= item.qty
|
||||||
|
|
||||||
if manufacturing_qty > (produced_qty + flt(self.fg_completed_qty)):
|
if manufacturing_qty > (produced_qty + flt(self.fg_completed_qty)):
|
||||||
qty = (qty/trans_qty) * flt(self.fg_completed_qty)
|
qty = (qty/trans_qty) * flt(self.fg_completed_qty)
|
||||||
|
|
||||||
elif backflushed_materials.get(item.item_code):
|
elif backflushed_materials.get(item.item_code):
|
||||||
for d in backflushed_materials.get(item.item_code):
|
for d in backflushed_materials.get(item.item_code):
|
||||||
if d.get(item.warehouse):
|
if d.get(item.warehouse):
|
||||||
qty-= d.get(item.warehouse)
|
qty-= d.get(item.warehouse)
|
||||||
|
|
||||||
if qty > 0:
|
if qty > 0:
|
||||||
self.add_to_stock_entry_detail({
|
self.add_to_stock_entry_detail({
|
||||||
item.item_code: {
|
item.item_code: {
|
||||||
@ -729,7 +733,7 @@ class StockEntry(StockController):
|
|||||||
se_child.s_warehouse = self.from_warehouse
|
se_child.s_warehouse = self.from_warehouse
|
||||||
if se_child.t_warehouse==None:
|
if se_child.t_warehouse==None:
|
||||||
se_child.t_warehouse = self.to_warehouse
|
se_child.t_warehouse = self.to_warehouse
|
||||||
|
|
||||||
# in stock uom
|
# in stock uom
|
||||||
se_child.transfer_qty = flt(item_dict[d]["qty"])
|
se_child.transfer_qty = flt(item_dict[d]["qty"])
|
||||||
se_child.conversion_factor = 1.00
|
se_child.conversion_factor = 1.00
|
||||||
@ -761,7 +765,7 @@ class StockEntry(StockController):
|
|||||||
def get_production_order_details(production_order):
|
def get_production_order_details(production_order):
|
||||||
production_order = frappe.get_doc("Production Order", production_order)
|
production_order = frappe.get_doc("Production Order", production_order)
|
||||||
pending_qty_to_produce = flt(production_order.qty) - flt(production_order.produced_qty)
|
pending_qty_to_produce = flt(production_order.qty) - flt(production_order.produced_qty)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"from_bom": 1,
|
"from_bom": 1,
|
||||||
"bom_no": production_order.bom_no,
|
"bom_no": production_order.bom_no,
|
||||||
@ -771,7 +775,7 @@ def get_production_order_details(production_order):
|
|||||||
"fg_completed_qty": pending_qty_to_produce,
|
"fg_completed_qty": pending_qty_to_produce,
|
||||||
"additional_costs": get_additional_costs(production_order, fg_qty=pending_qty_to_produce)
|
"additional_costs": get_additional_costs(production_order, fg_qty=pending_qty_to_produce)
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_additional_costs(production_order=None, bom_no=None, fg_qty=None):
|
def get_additional_costs(production_order=None, bom_no=None, fg_qty=None):
|
||||||
additional_costs = []
|
additional_costs = []
|
||||||
operating_cost_per_unit = get_operating_cost_per_unit(production_order, bom_no)
|
operating_cost_per_unit = get_operating_cost_per_unit(production_order, bom_no)
|
||||||
@ -780,33 +784,33 @@ def get_additional_costs(production_order=None, bom_no=None, fg_qty=None):
|
|||||||
"description": "Operating Cost as per Production Order / BOM",
|
"description": "Operating Cost as per Production Order / BOM",
|
||||||
"amount": operating_cost_per_unit * flt(fg_qty)
|
"amount": operating_cost_per_unit * flt(fg_qty)
|
||||||
})
|
})
|
||||||
|
|
||||||
if production_order and production_order.additional_operating_cost:
|
if production_order and production_order.additional_operating_cost:
|
||||||
additional_operating_cost_per_unit = \
|
additional_operating_cost_per_unit = \
|
||||||
flt(production_order.additional_operating_cost) / flt(production_order.qty)
|
flt(production_order.additional_operating_cost) / flt(production_order.qty)
|
||||||
|
|
||||||
additional_costs.append({
|
additional_costs.append({
|
||||||
"description": "Additional Operating Cost",
|
"description": "Additional Operating Cost",
|
||||||
"amount": additional_operating_cost_per_unit * flt(fg_qty)
|
"amount": additional_operating_cost_per_unit * flt(fg_qty)
|
||||||
})
|
})
|
||||||
|
|
||||||
return additional_costs
|
return additional_costs
|
||||||
|
|
||||||
def get_operating_cost_per_unit(production_order=None, bom_no=None):
|
def get_operating_cost_per_unit(production_order=None, bom_no=None):
|
||||||
operating_cost_per_unit = 0
|
operating_cost_per_unit = 0
|
||||||
if production_order:
|
if production_order:
|
||||||
if not bom_no:
|
if not bom_no:
|
||||||
bom_no = production_order.bom_no
|
bom_no = production_order.bom_no
|
||||||
|
|
||||||
for d in production_order.get("operations"):
|
for d in production_order.get("operations"):
|
||||||
if flt(d.completed_qty):
|
if flt(d.completed_qty):
|
||||||
operating_cost_per_unit += flt(d.actual_operating_cost) / flt(d.completed_qty)
|
operating_cost_per_unit += flt(d.actual_operating_cost) / flt(d.completed_qty)
|
||||||
else:
|
else:
|
||||||
operating_cost_per_unit += flt(d.planned_operating_cost) / flt(production_order.qty)
|
operating_cost_per_unit += flt(d.planned_operating_cost) / flt(production_order.qty)
|
||||||
|
|
||||||
# Get operating cost from BOM if not found in production_order.
|
# Get operating cost from BOM if not found in production_order.
|
||||||
if not operating_cost_per_unit and bom_no:
|
if not operating_cost_per_unit and bom_no:
|
||||||
bom = frappe.db.get_value("BOM", bom_no, ["operating_cost", "quantity"], as_dict=1)
|
bom = frappe.db.get_value("BOM", bom_no, ["operating_cost", "quantity"], as_dict=1)
|
||||||
operating_cost_per_unit = flt(bom.operating_cost) / flt(bom.quantity)
|
operating_cost_per_unit = flt(bom.operating_cost) / flt(bom.quantity)
|
||||||
|
|
||||||
return operating_cost_per_unit
|
return operating_cost_per_unit
|
||||||
|
@ -40,10 +40,10 @@
|
|||||||
{% if(in_list(["Sales Order Item", "Purchase Order Item"],
|
{% if(in_list(["Sales Order Item", "Purchase Order Item"],
|
||||||
doc.doctype) && frm.doc.docstatus===1) {
|
doc.doctype) && frm.doc.docstatus===1) {
|
||||||
var delivered = doc.doctype==="Sales Order Item" ?
|
var delivered = doc.doctype==="Sales Order Item" ?
|
||||||
doc.delivered_qty : doc.received_qty,
|
doc.delivered_qty : doc.received_qty;
|
||||||
pending = flt(doc.qty) - flt(delivered);
|
var pending = flt(doc.qty) - flt(delivered);
|
||||||
%}
|
%}
|
||||||
<span class="indicator {%= pending ? "orange" : "green" %}">{%= doc.item_code %}</span>
|
<span class="indicator {%= pending>0 ? "orange" : "green" %}">{%= doc.item_code %}</span>
|
||||||
{% } else { %}
|
{% } else { %}
|
||||||
<strong>{%= doc.item_code %}</strong>
|
<strong>{%= doc.item_code %}</strong>
|
||||||
{% } %}
|
{% } %}
|
||||||
|
@ -27,22 +27,31 @@
|
|||||||
{{ _("Item Code") }}: <span itemprop="productID">{{ name }}</span></p>
|
{{ _("Item Code") }}: <span itemprop="productID">{{ name }}</span></p>
|
||||||
<br>
|
<br>
|
||||||
<div style="min-height: 100px; margin: 10px 0;">
|
<div style="min-height: 100px; margin: 10px 0;">
|
||||||
<div class="item-price-info" style="display: none;">
|
<h4 class="item-price" itemprop="price"></h4>
|
||||||
<h4 class="item-price" itemprop="price"></h4>
|
<div class="item-stock" itemprop="availablity"></div>
|
||||||
<div class="item-stock" itemprop="availablity"></div>
|
<div class="item-cart hide">
|
||||||
<div id="item-add-to-cart">
|
<div id="item-add-to-cart">
|
||||||
<button class="btn btn-primary">
|
<button class="btn btn-primary btn-sm">
|
||||||
<i class="icon-shopping-cart"></i> + {{ _("Add to Cart") }}</button>
|
{{ _("Add to Cart") }}</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="item-update-cart" class="input-group col-md-4" style="display: none;
|
<div id="item-update-cart"
|
||||||
padding-left: 0px; padding-right: 0px;">
|
style="display: none;
|
||||||
<input class="form-control" type="text">
|
padding-left: 0px; padding-right: 0px;
|
||||||
<div class="input-group-btn">
|
padding-top: 10px;">
|
||||||
<button class="btn btn-primary">
|
<div>
|
||||||
<i class="icon-ok"></i></button>
|
<input class="form-control"
|
||||||
</div>
|
type="text" style="max-width: 140px;">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div style="margin-top: 10px;">
|
||||||
|
<button class="btn btn-default btn-sm">
|
||||||
|
{{ _("Update") }}</button>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 5px;">
|
||||||
|
<a href="/cart" class="text-muted small">
|
||||||
|
{{ _("View Cart") }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,19 +1,8 @@
|
|||||||
<div class="web-list-item">
|
<div class="web-list-item">
|
||||||
<a href="/addresses?name={{ doc.name }}" no-pjax>
|
<a href="/addresses?name={{ doc.name }}" no-pjax class="no-decoration">
|
||||||
<div class="row">
|
<h4 class="strong">{{ doc.address_title }}</h4>
|
||||||
<div class="col-sm-4">
|
<p class="text-muted small">
|
||||||
<span class="strong">{{ doc.address_title }}</span>
|
{{ frappe.get_doc(doc).get_display() }}
|
||||||
</div>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
{{ doc.address_type }}
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
{{ doc.address_line1 }}<br>
|
|
||||||
{% if doc.address_line2 %}{{ doc.address_line2 }}<br>{% endif %}
|
|
||||||
{{ doc.city }}<br>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
{% if doc.state %}{{ doc.state }}, {% endif %}{{ doc.country }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
25
erpnext/templates/includes/cart.css
Normal file
25
erpnext/templates/includes/cart.css
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
.cart-content {
|
||||||
|
min-height: 400px;
|
||||||
|
margin-top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-header, .cart-footer {
|
||||||
|
margin-bottom: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-item-header {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-bottom: 1px solid #d1d8dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tax-grand-total-row {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 30px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-addresses {
|
||||||
|
margin-top: 80px;
|
||||||
|
margin-bottom: 60px;
|
||||||
|
}
|
@ -13,126 +13,64 @@ $.extend(shopping_cart, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
bind_events: function() {
|
bind_events: function() {
|
||||||
// bind update button
|
shopping_cart.bind_address_select();
|
||||||
$(document).on("click", ".item-update-cart button", function() {
|
shopping_cart.bind_place_order();
|
||||||
var item_code = $(this).attr("data-item-code");
|
shopping_cart.bind_change_qty();
|
||||||
shopping_cart.update_cart({
|
|
||||||
item_code: item_code,
|
},
|
||||||
qty: $('input[data-item-code="'+item_code+'"]').val(),
|
|
||||||
with_doc: 1,
|
bind_address_select: function() {
|
||||||
btn: this,
|
$(".cart-addresses").find('input[data-address-name]').on("click", function() {
|
||||||
callback: function(r) {
|
if($(this).prop("checked")) {
|
||||||
if(!r.exc) {
|
var me = this;
|
||||||
shopping_cart.render(r.message);
|
|
||||||
var $button = $('button[data-item-code="'+item_code+'"]').addClass("btn-success");
|
return frappe.call({
|
||||||
setTimeout(function() { $button.removeClass("btn-success"); }, 1000);
|
type: "POST",
|
||||||
|
method: "erpnext.shopping_cart.cart.update_cart_address",
|
||||||
|
args: {
|
||||||
|
address_fieldname: $(this).attr("data-fieldname"),
|
||||||
|
address_name: $(this).attr("data-address-name")
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if(!r.exc) {
|
||||||
|
$(".cart-tax-items").html(r.message.taxes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
});
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#cart-add-shipping-address").on("click", function() {
|
},
|
||||||
window.location.href = "addresses";
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#cart-add-billing-address").on("click", function() {
|
|
||||||
window.location.href = "address";
|
|
||||||
});
|
|
||||||
|
|
||||||
|
bind_place_order: function() {
|
||||||
$(".btn-place-order").on("click", function() {
|
$(".btn-place-order").on("click", function() {
|
||||||
shopping_cart.place_order(this);
|
shopping_cart.place_order(this);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function(out) {
|
bind_change_qty: function() {
|
||||||
var doc = out.doc;
|
// bind update button
|
||||||
var addresses = out.addresses;
|
$(".cart-items").on("change", ".cart-qty", function() {
|
||||||
|
var item_code = $(this).attr("data-item-code");
|
||||||
var $cart_items = $("#cart-items").empty();
|
frappe.freeze();
|
||||||
var $cart_taxes = $("#cart-taxes").empty();
|
shopping_cart.update_cart({
|
||||||
var $cart_totals = $("#cart-totals").empty();
|
item_code: item_code,
|
||||||
var $cart_billing_address = $("#cart-billing-address").empty();
|
qty: $(this).val(),
|
||||||
var $cart_shipping_address = $("#cart-shipping-address").empty();
|
with_items: 1,
|
||||||
|
btn: this,
|
||||||
var no_items = $.map(doc.items || [],
|
callback: function(r) {
|
||||||
function(d) { return d.item_code || null;}).length===0;
|
frappe.unfreeze();
|
||||||
if(no_items) {
|
if(!r.exc) {
|
||||||
shopping_cart.show_error("Cart Empty", frappe._("Go ahead and add something to your cart."));
|
$(".cart-items").html(r.message.items);
|
||||||
$("#cart-addresses").toggle(false);
|
$(".cart-tax-items").html(r.message.taxes);
|
||||||
return;
|
}
|
||||||
}
|
$(".tax-grand-total").temp_highlight();
|
||||||
|
},
|
||||||
var shipping_rule_added = false;
|
});
|
||||||
var taxes_exist = false;
|
|
||||||
var shipping_rule_labels = $.map(out.shipping_rules || [], function(rule) { return rule[1]; });
|
|
||||||
|
|
||||||
$.each(doc.items || [], function(i, d) {
|
|
||||||
shopping_cart.render_item_row($cart_items, d);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$.each(doc.taxes || [], function(i, d) {
|
|
||||||
if(out.shipping_rules && out.shipping_rules.length &&
|
|
||||||
shipping_rule_labels.indexOf(d.description)!==-1) {
|
|
||||||
shipping_rule_added = true;
|
|
||||||
shopping_cart.render_tax_row($cart_taxes, d, out.shipping_rules);
|
|
||||||
} else {
|
|
||||||
shopping_cart.render_tax_row($cart_taxes, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
taxes_exist = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(out.shipping_rules && out.shipping_rules.length && !shipping_rule_added) {
|
|
||||||
shopping_cart.render_tax_row($cart_taxes, {description: "", formatted_tax_amount: ""},
|
|
||||||
out.shipping_rules);
|
|
||||||
taxes_exist = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(taxes_exist)
|
|
||||||
$('<hr>').appendTo($cart_taxes);
|
|
||||||
|
|
||||||
shopping_cart.render_tax_row($cart_totals, {
|
|
||||||
description: "<strong>Total</strong>",
|
|
||||||
formatted_tax_amount: "<strong>" + doc.formatted_grand_total_export + "</strong>"
|
|
||||||
});
|
|
||||||
|
|
||||||
if(!(addresses && addresses.length)) {
|
|
||||||
$cart_shipping_address.html('<div class="msg-box">'+frappe._("Hey! Go ahead and add an address")+'</div>');
|
|
||||||
} else {
|
|
||||||
shopping_cart.render_address($cart_shipping_address, addresses, doc.shipping_address_name);
|
|
||||||
shopping_cart.render_address($cart_billing_address, addresses, doc.customer_address);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
render_item_row: function($cart_items, doc) {
|
|
||||||
doc.image_html = doc.website_image ?
|
|
||||||
'<div style="height: 120px; overflow: hidden;"><img src="' + doc.website_image + '" /></div>': "";
|
|
||||||
|
|
||||||
if(doc.description === doc.item_name) doc.description = "";
|
|
||||||
|
|
||||||
$(repl('<div class="row">\
|
|
||||||
<div class="col-md-9 col-sm-9">\
|
|
||||||
<div class="row">\
|
|
||||||
<div class="col-md-3">%(image_html)s</div>\
|
|
||||||
<div class="col-md-9">\
|
|
||||||
<h4><a href="%(page_name)s">%(item_name)s</a></h4>\
|
|
||||||
<p>%(description)s</p>\
|
|
||||||
</div>\
|
|
||||||
</div>\
|
|
||||||
</div>\
|
|
||||||
<div class="col-md-3 col-sm-3 text-right">\
|
|
||||||
<div class="input-group item-update-cart">\
|
|
||||||
<input type="text" placeholder="Qty" value="%(qty)s" \
|
|
||||||
data-item-code="%(item_code)s" class="text-right form-control">\
|
|
||||||
<div class="input-group-btn">\
|
|
||||||
<button class="btn btn-primary" data-item-code="%(item_code)s">\
|
|
||||||
<i class="icon-ok"></i></button>\
|
|
||||||
</div>\
|
|
||||||
</div>\
|
|
||||||
<p style="margin-top: 10px;">at %(formatted_rate)s</p>\
|
|
||||||
<small class="text-muted" style="margin-top: 10px;">= %(formatted_amount)s</small>\
|
|
||||||
</div>\
|
|
||||||
</div><hr>', doc)).appendTo($cart_items);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render_tax_row: function($cart_taxes, doc, shipping_rules) {
|
render_tax_row: function($cart_taxes, doc, shipping_rules) {
|
||||||
@ -182,72 +120,6 @@ $.extend(shopping_cart, {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
render_address: function($address_wrapper, addresses, address_name) {
|
|
||||||
$.each(addresses, function(i, address) {
|
|
||||||
$(repl('<div class="panel panel-default"> \
|
|
||||||
<div class="panel-heading"> \
|
|
||||||
<div class="row"> \
|
|
||||||
<div class="col-md-10 address-title" \
|
|
||||||
data-address-name="%(name)s"><strong>%(name)s</strong></div> \
|
|
||||||
<div class="col-md-2"><input type="checkbox" \
|
|
||||||
data-address-name="%(name)s"></div> \
|
|
||||||
</div> \
|
|
||||||
</div> \
|
|
||||||
<div class="panel-collapse collapse" data-address-name="%(name)s"> \
|
|
||||||
<div class="panel-body">%(display)s</div> \
|
|
||||||
</div> \
|
|
||||||
</div>', address))
|
|
||||||
.css({"margin": "10px auto"})
|
|
||||||
.appendTo($address_wrapper);
|
|
||||||
});
|
|
||||||
|
|
||||||
$address_wrapper.find(".panel-heading")
|
|
||||||
.find(".address-title")
|
|
||||||
.css({"cursor": "pointer"})
|
|
||||||
.on("click", function() {
|
|
||||||
$address_wrapper.find('.panel-collapse[data-address-name="'
|
|
||||||
+$(this).attr("data-address-name")+'"]').collapse("toggle");
|
|
||||||
});
|
|
||||||
|
|
||||||
$address_wrapper.find('input[type="checkbox"]').on("click", function() {
|
|
||||||
if($(this).prop("checked")) {
|
|
||||||
var me = this;
|
|
||||||
$address_wrapper.find('input[type="checkbox"]').each(function(i, chk) {
|
|
||||||
if($(chk).attr("data-address-name")!=$(me).attr("data-address-name")) {
|
|
||||||
$(chk).prop("checked", false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return frappe.call({
|
|
||||||
type: "POST",
|
|
||||||
method: "erpnext.shopping_cart.cart.update_cart_address",
|
|
||||||
args: {
|
|
||||||
address_fieldname: $address_wrapper.attr("data-fieldname"),
|
|
||||||
address_name: $(this).attr("data-address-name")
|
|
||||||
},
|
|
||||||
callback: function(r) {
|
|
||||||
if(!r.exc) {
|
|
||||||
shopping_cart.render(r.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$address_wrapper.find('input[type="checkbox"][data-address-name="'+ address_name +'"]')
|
|
||||||
.prop("checked", true);
|
|
||||||
|
|
||||||
$address_wrapper.find(".panel-collapse").collapse({
|
|
||||||
parent: $address_wrapper,
|
|
||||||
toggle: false
|
|
||||||
});
|
|
||||||
|
|
||||||
$address_wrapper.find('.panel-collapse[data-address-name="'+ address_name +'"]')
|
|
||||||
.collapse("show");
|
|
||||||
},
|
|
||||||
|
|
||||||
place_order: function(btn) {
|
place_order: function(btn) {
|
||||||
return frappe.call({
|
return frappe.call({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
@ -274,24 +146,4 @@ $.extend(shopping_cart, {
|
|||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
shopping_cart.bind_events();
|
shopping_cart.bind_events();
|
||||||
return frappe.call({
|
|
||||||
type: "POST",
|
|
||||||
method: "erpnext.shopping_cart.cart.get_cart_quotation",
|
|
||||||
callback: function(r) {
|
|
||||||
$("#cart-container").removeClass("hide");
|
|
||||||
$(".progress").remove();
|
|
||||||
if(r.exc) {
|
|
||||||
if(r.exc.indexOf("WebsitePriceListMissingError")!==-1) {
|
|
||||||
shopping_cart.show_error("Configuration Error", frappe._("Price List not configured."));
|
|
||||||
} else if(r["403"]) {
|
|
||||||
shopping_cart.show_error("Not Allowed", frappe._("You need to be logged in to view your cart."));
|
|
||||||
} else {
|
|
||||||
shopping_cart.show_error("Error", frappe._("Something went wrong."));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
shopping_cart.set_cart_count();
|
|
||||||
shopping_cart.render(r.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
24
erpnext/templates/includes/cart/cart_address.html
Normal file
24
erpnext/templates/includes/cart/cart_address.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{% from "erpnext/templates/includes/cart/cart_macros.html"
|
||||||
|
import show_address %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<h4>{{ _("Shipping Address") }}</h4>
|
||||||
|
<div id="cart-shipping-address" class="panel-group"
|
||||||
|
data-fieldname="shipping_address_name">
|
||||||
|
{% for address in addresses %}
|
||||||
|
{{ show_address(address, doc, "shipping_address_name") }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<a class="btn btn-default btn-sm" href="/addresses">
|
||||||
|
{{ _("Manage Addresses") }}</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<h4>Billing Address</h4>
|
||||||
|
<div id="cart-billing-address" class="panel-group"
|
||||||
|
data-fieldname="customer_address">
|
||||||
|
{% for address in addresses %}
|
||||||
|
{{ show_address(address, doc, "customer_address") }}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
23
erpnext/templates/includes/cart/cart_items.html
Normal file
23
erpnext/templates/includes/cart/cart_items.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{% from "erpnext/templates/includes/order/order_macros.html" import item_name_and_description %}
|
||||||
|
|
||||||
|
{% for d in doc.items %}
|
||||||
|
<div class="cart-item">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-8 col-xs-6" style="margin-bottom: 10px;">
|
||||||
|
{{ item_name_and_description(d) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 col-xs-3 text-right">
|
||||||
|
<span style="max-width: 50px; display: inline-block">
|
||||||
|
<input class="form-control text-right cart-qty"
|
||||||
|
value = "{{ d.get_formatted('qty') }}"
|
||||||
|
data-item-code="{{ d.item_code }}"></span>
|
||||||
|
<p class="text-muted small" style="margin-top: 10px;">
|
||||||
|
{{ _("Rate") + ': ' + d.get_formatted("rate") }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 col-xs-3 text-right">
|
||||||
|
{{ d.get_formatted("amount") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
21
erpnext/templates/includes/cart/cart_macros.html
Normal file
21
erpnext/templates/includes/cart/cart_macros.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{% macro show_address(address, doc, fieldname) %}
|
||||||
|
{% set selected=address.name==doc.get(fieldname) %}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-10 address-title"
|
||||||
|
data-address-name="{{ address.name }}">
|
||||||
|
<strong>{{ address.name }}</strong></div>
|
||||||
|
<div class="col-sm-2 text-right">
|
||||||
|
<input type="checkbox"
|
||||||
|
data-fieldname="{{ fieldname }}"
|
||||||
|
data-address-name="{{ address.name}}"
|
||||||
|
{{ "checked" if selected else "" }}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-collapse"
|
||||||
|
data-address-name="{{ address.name }}">
|
||||||
|
<div class="panel-body text-muted small">{{ address.display }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
@ -1,21 +1,15 @@
|
|||||||
<div class="web-list-item">
|
<div class="web-list-item">
|
||||||
|
<a class="no-decoration" href="/issues?name={{ doc.name }}" no-pjax>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6">
|
<div class="col-xs-8">
|
||||||
<a class="no-decoration" href="/issues?name={{ doc.name }}" no-pjax>
|
<span class="indicator {{ "red" if doc.status=="Open" else "darkgrey" }}">
|
||||||
{{ doc.subject }}
|
{{ doc.name }}</span>
|
||||||
</a>
|
<span style="margin-left: 15px;">
|
||||||
|
{{ doc.subject }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2">
|
<div class="col-xs-4 text-right small text-muted">
|
||||||
<span class="indicator {{ "red" if doc.status=="Open" else "blue" }}">
|
{{ frappe.format_date(doc.modified) }}
|
||||||
{{ doc.status }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
<a class="text-muted text-right" href="/issues?name={{ doc.name }}" no-pjax>
|
|
||||||
{{ doc.name }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2 text-muted text-right small">
|
|
||||||
{{ frappe.format_date(doc.creation) }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,11 +6,12 @@
|
|||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro product_image(website_image, css_class="") %}
|
{% macro product_image(website_image, css_class="") %}
|
||||||
<div class="product-image {% if not website_image -%} missing-image {%- endif %} {{ css_class }}">
|
<div class="product-image {% if not website_image -%} missing-image {%- endif %} {{ css_class }}">
|
||||||
{% if website_image -%}
|
{% if website_image -%}
|
||||||
<img src="{{ frappe.utils.quoted(website_image) | abs_url }}" class="img-responsive">
|
<img src="{{ frappe.utils.quoted(website_image) | abs_url }}" class="img-responsive">
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
<i class="centered octicon octicon-device-camera"></i>
|
<i class="centered octicon octicon-device-camera"></i>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
25
erpnext/templates/includes/order/order.css
Normal file
25
erpnext/templates/includes/order/order.css
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
.order-container {
|
||||||
|
margin: 50px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-items {
|
||||||
|
margin: 20px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-item-table {
|
||||||
|
margin: 0px -15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-item-header {
|
||||||
|
border-bottom: 1px solid #d1d8dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-image-col {
|
||||||
|
padding-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-image {
|
||||||
|
max-width: 55px;
|
||||||
|
max-height: 55px;
|
||||||
|
margin-top: -5px;
|
||||||
|
}
|
15
erpnext/templates/includes/order/order_macros.html
Normal file
15
erpnext/templates/includes/order/order_macros.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{% from "erpnext/templates/includes/macros.html" import product_image_square %}
|
||||||
|
|
||||||
|
{% macro item_name_and_description(d) %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-4 col-sm-2 order-image-col">
|
||||||
|
<div class="order-image">
|
||||||
|
{{ product_image_square(d.image) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-8 col-sm-10">
|
||||||
|
{{ d.item_code }}
|
||||||
|
<p class="text-muted small">{{ d.description }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
22
erpnext/templates/includes/order/order_taxes.html
Normal file
22
erpnext/templates/includes/order/order_taxes.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{% if doc.taxes %}
|
||||||
|
<div class="row tax-net-total-row">
|
||||||
|
<div class="col-xs-6 text-right">{{ _("Net Total") }}</div>
|
||||||
|
<div class="col-xs-6 text-right">
|
||||||
|
{{ doc.get_formatted("net_total") }}</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% for d in doc.taxes %}
|
||||||
|
<div class="row tax-row">
|
||||||
|
<div class="col-xs-6 text-right">{{ d.description }}</div>
|
||||||
|
<div class="col-xs-6 text-right">
|
||||||
|
{{ d.get_formatted("base_tax_amount") }}</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="row tax-grand-total-row">
|
||||||
|
<div class="col-xs-6 text-right">{{ _("Grand Total") }}</div>
|
||||||
|
<div class="col-xs-6 text-right">
|
||||||
|
<span class="tax-grand-total">
|
||||||
|
{{ doc.get_formatted("grand_total") }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -1,10 +1,10 @@
|
|||||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
$(document).ready(function() {
|
frappe.ready(function() {
|
||||||
var item_code = $('[itemscope] [itemprop="productID"]').text().trim();
|
var item_code = $('[itemscope] [itemprop="productID"]').text().trim();
|
||||||
var qty = 0;
|
var qty = 0;
|
||||||
|
|
||||||
frappe.call({
|
frappe.call({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
method: "erpnext.shopping_cart.product.get_product_info",
|
method: "erpnext.shopping_cart.product.get_product_info",
|
||||||
@ -12,10 +12,12 @@ $(document).ready(function() {
|
|||||||
item_code: "{{ name }}"
|
item_code: "{{ name }}"
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
|
console.log(r.message);
|
||||||
|
$(".item-cart").toggleClass("hide", !!!r.message.price);
|
||||||
if(r.message && r.message.price) {
|
if(r.message && r.message.price) {
|
||||||
$(".item-price")
|
$(".item-price")
|
||||||
.html(r.message.price.formatted_price + " per " + r.message.uom);
|
.html(r.message.price.formatted_price + " per " + r.message.uom);
|
||||||
|
|
||||||
if(r.message.stock==0) {
|
if(r.message.stock==0) {
|
||||||
$(".item-stock").html("<div class='help'>Not in stock</div>");
|
$(".item-stock").html("<div class='help'>Not in stock</div>");
|
||||||
}
|
}
|
||||||
@ -23,18 +25,17 @@ $(document).ready(function() {
|
|||||||
$(".item-stock").html("<div style='color: green'>\
|
$(".item-stock").html("<div style='color: green'>\
|
||||||
<i class='icon-check'></i> Available (in stock)</div>");
|
<i class='icon-check'></i> Available (in stock)</div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
$(".item-price-info").toggle(true);
|
|
||||||
|
|
||||||
if(r.message.qty) {
|
if(r.message.qty) {
|
||||||
qty = r.message.qty;
|
qty = r.message.qty;
|
||||||
toggle_update_cart(qty);
|
toggle_update_cart(r.message.qty);
|
||||||
$("#item-update-cart input").val(qty);
|
} else {
|
||||||
|
toggle_update_cart(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
$("#item-add-to-cart button").on("click", function() {
|
$("#item-add-to-cart button").on("click", function() {
|
||||||
shopping_cart.update_cart({
|
shopping_cart.update_cart({
|
||||||
item_code: item_code,
|
item_code: item_code,
|
||||||
@ -45,10 +46,10 @@ $(document).ready(function() {
|
|||||||
qty = 1;
|
qty = 1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
btn: this,
|
btn: this,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#item-update-cart button").on("click", function() {
|
$("#item-update-cart button").on("click", function() {
|
||||||
shopping_cart.update_cart({
|
shopping_cart.update_cart({
|
||||||
item_code: item_code,
|
item_code: item_code,
|
||||||
@ -63,7 +64,7 @@ $(document).ready(function() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if(localStorage && localStorage.getItem("pending_add_to_cart") && full_name) {
|
if(localStorage && localStorage.getItem("pending_add_to_cart") && full_name) {
|
||||||
localStorage.removeItem("pending_add_to_cart");
|
localStorage.removeItem("pending_add_to_cart");
|
||||||
$("#item-add-to-cart button").trigger("click");
|
$("#item-add-to-cart button").trigger("click");
|
||||||
@ -75,4 +76,4 @@ var toggle_update_cart = function(qty) {
|
|||||||
$("#item-update-cart")
|
$("#item-update-cart")
|
||||||
.toggle(qty ? true : false)
|
.toggle(qty ? true : false)
|
||||||
.find("input").val(qty);
|
.find("input").val(qty);
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,22 @@
|
|||||||
{% set doc = frappe.get_doc(doc) %}
|
|
||||||
<div class="web-list-item">
|
<div class="web-list-item">
|
||||||
<a href="/{{ pathname }}/{{ doc.name }}" no-pjax>
|
<a href="/{{ pathname }}/{{ doc.name }}" no-pjax>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6 col-xs-7">
|
<div class="col-sm-8 col-xs-7">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-9">{{ doc.customer or doc.supplier }}</div>
|
<div class="col-sm-9">
|
||||||
|
<div>{{ doc.name }}</div>
|
||||||
|
<div class="small text-muted">{{ doc.items_preview }}</div>
|
||||||
|
</div>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
{%- if doc.status_percent > 0 -%}
|
<span class="indicator {{ doc.indicator_color or "darkgrey" }}">
|
||||||
{%- if doc.status_percent % 100 == 0 -%}
|
{{ doc.indicator_title or doc.status or "Submitted" }}
|
||||||
<span class="indicator green">{{ doc.status_display }}</span>
|
</span>
|
||||||
{%- else -%}
|
|
||||||
<span class="indicator orange">{{ doc.status_display }}</span>
|
|
||||||
{%- endif -%}
|
|
||||||
{%- elif doc.status -%}
|
|
||||||
<span class="indicator blue">{{ doc.status }}</span>
|
|
||||||
{%- endif -%}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2 col-xs-5 text-right">
|
<div class="col-sm-2 col-xs-5 text-right">
|
||||||
{{ doc.get_formatted("grand_total") }}
|
{{ doc.get_formatted("grand_total") }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2 text-muted text-right">
|
|
||||||
{{ doc.name }}
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2 small text-muted text-right" title="{{ frappe.utils.format_datetime(doc.creation, "medium") }}">
|
<div class="col-sm-2 small text-muted text-right" title="{{ frappe.utils.format_datetime(doc.creation, "medium") }}">
|
||||||
{{ frappe.utils.pretty_date(doc.creation) }}</div>
|
{{ frappe.utils.pretty_date(doc.creation) }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,53 +3,63 @@
|
|||||||
{% block header %}<h2>{{ _("My Cart") }}</h2>{% endblock %}
|
{% block header %}<h2>{{ _("My Cart") }}</h2>{% endblock %}
|
||||||
|
|
||||||
{% block script %}{% include "templates/includes/cart.js" %}{% endblock %}
|
{% block script %}{% include "templates/includes/cart.js" %}{% endblock %}
|
||||||
|
{% block style %}{% include "templates/includes/cart.css" %}{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block header_actions %}
|
||||||
|
{% if doc.items %}
|
||||||
|
<button class="btn btn-primary btn-place-order btn-sm"
|
||||||
|
type="button">
|
||||||
|
{{ _("Place Order") }}</button>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
{% from "templates/includes/macros.html" import item_name_and_description %}
|
||||||
|
|
||||||
<div class="cart-content">
|
<div class="cart-content">
|
||||||
<div class="text-muted progress">{{ _("Loading") }}...</div>
|
<div id="cart-container">
|
||||||
<div id="cart-container" class="hide">
|
<div id="cart-error" class="alert alert-danger"
|
||||||
<p class="pull-right"><button class="btn btn-success btn-place-order" type="button">
|
style="display: none;"></div>
|
||||||
{{ _("Place Order") }}</button></p>
|
<div id="cart-items">
|
||||||
<div class="clearfix"></div>
|
<div class="row cart-item-header">
|
||||||
<div id="cart-error" class="alert alert-danger" style="display: none;"></div>
|
<div class="col-sm-8 col-xs-6">
|
||||||
<hr>
|
Items
|
||||||
<div class="row">
|
</div>
|
||||||
<div class="col-md-9 col-sm-9">
|
<div class="col-sm-2 col-xs-3 text-right">
|
||||||
<div class="row">
|
Qty
|
||||||
<div class="col-md-9 col-md-offset-3"><h4>{{ _("Item Details") }}</h4></div>
|
</div>
|
||||||
</div>
|
<div class="col-sm-2 col-xs-3 text-right">
|
||||||
</div>
|
Amount
|
||||||
<div class="col-md-3 col-sm-3 text-right"><h4>{{ _("Qty, Amount") }}</h4></div>
|
</div>
|
||||||
</div><hr>
|
</div>
|
||||||
<div id="cart-items">
|
{% if doc.items %}
|
||||||
</div>
|
<div class="cart-items">
|
||||||
<div id="cart-taxes">
|
{% include "templates/includes/cart/cart_items.html" %}
|
||||||
</div>
|
</div>
|
||||||
<div id="cart-totals">
|
{% else %}
|
||||||
</div>
|
<p>{{ _("Cart is Empty") }}</p>
|
||||||
<hr>
|
{% endif %}
|
||||||
<div id="cart-addresses">
|
</div>
|
||||||
<div class="row">
|
{% if doc.items %}
|
||||||
<div class="col-md-6">
|
<!-- taxes -->
|
||||||
<h4>{{ _("Shipping Address") }}</h4>
|
<div class="cart-taxes row small">
|
||||||
<div id="cart-shipping-address" class="panel-group"
|
<div class="col-sm-8"><!-- empty --></div>
|
||||||
data-fieldname="shipping_address_name"></div>
|
<div class="col-sm-4 cart-tax-items">
|
||||||
<button class="btn btn-default" type="button" id="cart-add-shipping-address">
|
{% include "templates/includes/order/order_taxes.html" %}
|
||||||
<span class="icon icon-list"></span> {{ _("Manage Addresses") }}</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div id="cart-totals">
|
||||||
<h4>Billing Address</h4>
|
</div>
|
||||||
<div id="cart-billing-address" class="panel-group"
|
<div class="cart-addresses">
|
||||||
data-fieldname="customer_address"></div>
|
{% include "templates/includes/cart/cart_address.html" %}
|
||||||
<button class="btn btn-default" type="button" id="cart-add-billing-address">
|
</div>
|
||||||
<span class="icon icon-list"></span> {{ _("Manage Addresses") }}</button>
|
<p class="cart-footer text-right">
|
||||||
</div>
|
<button class="btn btn-primary btn-place-order btn-sm" type="button">
|
||||||
</div>
|
{{ _("Place Order") }}</button></p>
|
||||||
<hr>
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<p class="pull-right"><button class="btn btn-success btn-place-order" type="button">
|
|
||||||
{{ _("Place Order") }}</button></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- no-sidebar -->
|
<!-- no-sidebar -->
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
no_cache = 1
|
no_cache = 1
|
||||||
no_sitemap = 1
|
no_sitemap = 1
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from erpnext.shopping_cart.cart import get_cart_quotation
|
||||||
|
|
||||||
|
def get_context(context):
|
||||||
|
context.update(get_cart_quotation())
|
||||||
|
72
erpnext/templates/pages/order.html
Normal file
72
erpnext/templates/pages/order.html
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{% block header %}
|
||||||
|
<h1>{{ doc.name }}</h1>
|
||||||
|
<!-- <h6 class="text-muted">{{ doc._title or doc.doctype }}</h6> -->
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block style %}{% include "templates/includes/order/order.css" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% from "erpnext/templates/includes/order/order_macros.html" import item_name_and_description %}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<span class="indicator {{ doc.indicator_color or "darkgrey" }}">
|
||||||
|
{{ doc.indicator_title or doc.status or "Submitted" }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6 text-muted text-right h6">
|
||||||
|
{{ doc.get_formatted("transaction_date") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if doc._header %}
|
||||||
|
{{ doc._header }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="order-container">
|
||||||
|
|
||||||
|
<!-- items -->
|
||||||
|
<div class="order-item-table">
|
||||||
|
<div class="row order-items order-item-header">
|
||||||
|
<div class="col-sm-8 col-xs-6 h6">
|
||||||
|
{{ _("Item") }}
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 col-xs-3 text-right h6">
|
||||||
|
{{ _("Quantity") }}
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 col-xs-3 text-right h6">
|
||||||
|
{{ _("Amount") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% for d in doc.items %}
|
||||||
|
<div class="row order-items">
|
||||||
|
<div class="col-sm-8 col-xs-6">
|
||||||
|
{{ item_name_and_description(d) }}
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 col-xs-3 text-right">
|
||||||
|
{{ d.qty }}
|
||||||
|
{% if d.delivered_qty != None %}
|
||||||
|
<p class="text-muted small">{{
|
||||||
|
_("Delivered: {0}").format(d.delivered_qty) }}</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2 col-xs-3 text-right">
|
||||||
|
{{ d.get_formatted("amount") }}
|
||||||
|
<p class="text-muted small">{{
|
||||||
|
_("Rate: {0}").format(d.get_formatted("rate")) }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- taxes -->
|
||||||
|
<div class="order-taxes row small">
|
||||||
|
<div class="col-sm-8"><!-- empty --></div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
{% include "erpnext/templates/includes/order/order_taxes.html" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
18
erpnext/templates/pages/order.py
Normal file
18
erpnext/templates/pages/order.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_context(context):
|
||||||
|
context.no_cache = 1
|
||||||
|
context.doc = frappe.get_doc(frappe.form_dict.doctype, frappe.form_dict.name)
|
||||||
|
if hasattr(context.doc, "set_indicator"):
|
||||||
|
context.doc.set_indicator()
|
||||||
|
|
||||||
|
context.parents = frappe.form_dict.parents
|
||||||
|
|
||||||
|
if not context.doc.has_permission("read"):
|
||||||
|
frappe.throw(_("Not Permitted"), frappe.PermissionError)
|
@ -5,36 +5,31 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import cstr
|
from frappe.utils import cstr
|
||||||
from erpnext.shopping_cart.cart import get_lead_or_customer
|
from erpnext.shopping_cart.cart import get_customer
|
||||||
|
|
||||||
no_cache = 1
|
no_cache = 1
|
||||||
no_sitemap = 1
|
no_sitemap = 1
|
||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
party = get_lead_or_customer()
|
party = get_customer()
|
||||||
if party.doctype == "Lead":
|
mobile_no, phone = frappe.db.get_value("Contact", {"email_id": frappe.session.user,
|
||||||
mobile_no = party.mobile_no
|
"customer": party.name}, ["mobile_no", "phone"])
|
||||||
phone = party.phone
|
|
||||||
else:
|
|
||||||
mobile_no, phone = frappe.db.get_value("Contact", {"email_id": frappe.session.user,
|
|
||||||
"customer": party.name}, ["mobile_no", "phone"])
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"company_name": cstr(party.customer_name if party.doctype == "Customer" else party.company_name),
|
"company_name": cstr(party.customer_name if party.doctype == "Customer" else party.company_name),
|
||||||
"mobile_no": cstr(mobile_no),
|
"mobile_no": cstr(mobile_no),
|
||||||
"phone": cstr(phone)
|
"phone": cstr(phone)
|
||||||
}
|
}
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def update_user(fullname, password=None, company_name=None, mobile_no=None, phone=None):
|
def update_user(fullname, password=None, company_name=None, mobile_no=None, phone=None):
|
||||||
from erpnext.shopping_cart.cart import update_party
|
from erpnext.shopping_cart.cart import update_party
|
||||||
update_party(fullname, company_name, mobile_no, phone)
|
update_party(fullname, company_name, mobile_no, phone)
|
||||||
|
|
||||||
if not fullname:
|
if not fullname:
|
||||||
return _("Name is required")
|
return _("Name is required")
|
||||||
|
|
||||||
frappe.db.set_value("User", frappe.session.user, "first_name", fullname)
|
frappe.db.set_value("User", frappe.session.user, "first_name", fullname)
|
||||||
frappe.local.cookie_manager.set_cookie("full_name", fullname)
|
frappe.local.cookie_manager.set_cookie("full_name", fullname)
|
||||||
|
|
||||||
return _("Updated")
|
return _("Updated")
|
||||||
|
|
@ -70,6 +70,9 @@ class Address(Document):
|
|||||||
(is_address_type, fieldname, "%s", "%s"), (self.get(fieldname), self.name))
|
(is_address_type, fieldname, "%s", "%s"), (self.get(fieldname), self.name))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
def get_display(self):
|
||||||
|
return get_address_display(self.as_dict())
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_address_display(address_dict):
|
def get_address_display(address_dict):
|
||||||
if not address_dict:
|
if not address_dict:
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
"address_line1": "_Test Address Line 1",
|
"address_line1": "_Test Address Line 1",
|
||||||
"address_title": "_Test Address",
|
"address_title": "_Test Address",
|
||||||
"address_type": "Office",
|
"address_type": "Office",
|
||||||
"city": "_Test City",
|
"city": "_Test City",
|
||||||
|
"state": "Test State",
|
||||||
"country": "India",
|
"country": "India",
|
||||||
"customer": "_Test Customer",
|
"customer": "_Test Customer",
|
||||||
"customer_name": "_Test Customer",
|
"customer_name": "_Test Customer",
|
||||||
|
2
setup.py
2
setup.py
@ -1,6 +1,6 @@
|
|||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
version = "6.2.0"
|
version = "6.3.0"
|
||||||
|
|
||||||
with open("requirements.txt", "r") as f:
|
with open("requirements.txt", "r") as f:
|
||||||
install_requires = f.readlines()
|
install_requires = f.readlines()
|
||||||
|
Loading…
Reference in New Issue
Block a user