[shopping-cart] cart via Jinja WIP
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 030fddb..885e7bd 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -35,6 +35,15 @@
'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):
super(SalesInvoice, self).validate()
self.validate_posting_time()
@@ -90,7 +99,7 @@
# this sequence because outstanding may get -ve
self.make_gl_entries()
-
+
if not self.is_return:
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
self.check_credit_limit()
@@ -161,10 +170,10 @@
'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):
from erpnext.selling.doctype.customer.customer import check_credit_limit
-
+
validate_against_credit_limit = False
for d in self.get("items"):
if not (d.sales_order or d.delivery_note):
@@ -282,7 +291,7 @@
reconcile_against_document(lst)
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)
if account.report_type != "Balance Sheet":
@@ -290,7 +299,7 @@
if self.customer and account.account_type != "Receivable":
frappe.throw(_("Debit To account must be a Receivable account"))
-
+
self.party_account_currency = account.account_currency
def validate_fixed_asset_account(self):
@@ -437,18 +446,18 @@
if cint(self.is_pos) == 1:
if flt(self.paid_amount) == 0:
if self.cash_bank_account:
- frappe.db.set(self, 'paid_amount',
- flt(flt(self.grand_total) - flt(self.write_off_amount), self.precision("paid_amount")))
+ frappe.db.set(self, 'paid_amount',
+ flt(flt(self.grand_total) - flt(self.write_off_amount), self.precision("paid_amount")))
else:
# show message that the amount is not paid
frappe.db.set(self,'paid_amount',0)
frappe.msgprint(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
else:
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")))
-
+
def check_prev_docstatus(self):
for d in self.get('items'):
if d.sales_order and frappe.db.get_value("Sales Order", d.sales_order, "docstatus") != 1:
@@ -487,7 +496,7 @@
from erpnext.accounts.general_ledger import merge_similar_entries
gl_entries = []
-
+
self.make_customer_gl_entry(gl_entries)
self.make_tax_gl_entries(gl_entries)
@@ -586,7 +595,7 @@
# write off entries, applicable if only pos
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")
-
+
gl_entries.append(
self.get_gl_dict({
"account": self.debit_to,
diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py
index 9ec94eb..51fb0a5 100644
--- a/erpnext/controllers/website_list_for_contact.py
+++ b/erpnext/controllers/website_list_for_contact.py
@@ -66,6 +66,9 @@
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)
diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py
index e219d8e..6ff164b 100644
--- a/erpnext/shopping_cart/cart.py
+++ b/erpnext/shopping_cart/cart.py
@@ -122,7 +122,8 @@
quotation.flags.ignore_permissions = True
quotation.save()
- return get_cart_quotation(quotation)
+ return frappe.render_template("templates/includes/cart/cart_address.html",
+ get_cart_quotation(quotation))
def guess_territory():
territory = None
diff --git a/erpnext/templates/includes/cart.css b/erpnext/templates/includes/cart.css
index ed98846..7a18530 100644
--- a/erpnext/templates/includes/cart.css
+++ b/erpnext/templates/includes/cart.css
@@ -1,7 +1,25 @@
.cart-content {
min-height: 400px;
+ margin-top: 60px;
}
.cart-header, .cart-footer {
- margin-bottom: 40px;
+ 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;
}
diff --git a/erpnext/templates/includes/cart.js b/erpnext/templates/includes/cart.js
index 349e2f5..e0706f7 100644
--- a/erpnext/templates/includes/cart.js
+++ b/erpnext/templates/includes/cart.js
@@ -13,6 +13,8 @@
},
bind_events: function() {
+ shopping_cart.bind_address_select();
+
// bind update button
$(document).on("click", ".item-update-cart button", function() {
var item_code = $(this).attr("data-item-code");
@@ -31,19 +33,36 @@
});
});
- $("#cart-add-shipping-address").on("click", function() {
- window.location.href = "addresses";
- });
-
- $("#cart-add-billing-address").on("click", function() {
- window.location.href = "address";
- });
-
$(".btn-place-order").on("click", function() {
shopping_cart.place_order(this);
});
},
+ bind_address_select: function() {
+ $(".cart-addresses").find('input[data-address-name]').on("click", function() {
+ if($(this).prop("checked")) {
+ var me = this;
+
+ return frappe.call({
+ 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-addresses').html(r.message);
+ }
+ }
+ });
+ } else {
+ return false;
+ }
+ });
+
+ },
+
render: function(out) {
var doc = out.doc;
var addresses = out.addresses;
@@ -209,32 +228,6 @@
+$(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);
diff --git a/erpnext/templates/includes/cart/cart_address.html b/erpnext/templates/includes/cart/cart_address.html
new file mode 100644
index 0000000..44964da
--- /dev/null
+++ b/erpnext/templates/includes/cart/cart_address.html
@@ -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>
diff --git a/erpnext/templates/includes/cart/cart_item_line.html b/erpnext/templates/includes/cart/cart_item_line.html
new file mode 100644
index 0000000..cd15763
--- /dev/null
+++ b/erpnext/templates/includes/cart/cart_item_line.html
@@ -0,0 +1,16 @@
+{% from "erpnext/templates/includes/order/order_macros.html" import item_name_and_description %}
+
+<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">
+ <div>{{ d.get_formatted('qty') }}</div>
+ <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>
diff --git a/erpnext/templates/includes/cart/cart_macros.html b/erpnext/templates/includes/cart/cart_macros.html
new file mode 100644
index 0000000..250b487
--- /dev/null
+++ b/erpnext/templates/includes/cart/cart_macros.html
@@ -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 %}
diff --git a/erpnext/templates/includes/macros.html b/erpnext/templates/includes/macros.html
index 487968b..81a10c2 100644
--- a/erpnext/templates/includes/macros.html
+++ b/erpnext/templates/includes/macros.html
@@ -15,16 +15,3 @@
</div>
{% endmacro %}
-{% 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 %}
diff --git a/erpnext/templates/includes/order.css b/erpnext/templates/includes/order/order.css
similarity index 100%
rename from erpnext/templates/includes/order.css
rename to erpnext/templates/includes/order/order.css
diff --git a/erpnext/templates/includes/order/order_macros.html b/erpnext/templates/includes/order/order_macros.html
new file mode 100644
index 0000000..af974aa
--- /dev/null
+++ b/erpnext/templates/includes/order/order_macros.html
@@ -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 %}
diff --git a/erpnext/templates/includes/order/order_taxes.html b/erpnext/templates/includes/order/order_taxes.html
new file mode 100644
index 0000000..510e1a3
--- /dev/null
+++ b/erpnext/templates/includes/order/order_taxes.html
@@ -0,0 +1,19 @@
+{% 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">
+ {{ doc.get_formatted("grand_total") }}</div>
+</div>
diff --git a/erpnext/templates/pages/cart.html b/erpnext/templates/pages/cart.html
index 2e15728..837df3b 100644
--- a/erpnext/templates/pages/cart.html
+++ b/erpnext/templates/pages/cart.html
@@ -5,81 +5,62 @@
{% 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 %}
-{% from "erpnext/templates/includes/macros.html" import item_name_and_description %}
+{% from "templates/includes/macros.html" import item_name_and_description %}
<div class="cart-content">
- <p class="text-muted loading">{{ _("Loading") }}...</p>
<div id="cart-container">
- <div class="cart-header">
- <p class="pull-right"><button class="btn btn-primary btn-place-order btn-sm" type="button">
- {{ _("Place Order") }}</button></p>
- <div class="clearfix"></div>
- </div>
- <div id="cart-error" class="alert alert-danger" style="display: none;"></div>
+ <div id="cart-error" class="alert alert-danger"
+ style="display: none;"></div>
<div id="cart-items">
+ <div class="row cart-item-header">
+ <div class="col-sm-8 col-xs-6">
+ Items
+ </div>
+ <div class="col-sm-2 col-xs-3 text-right">
+ Qty
+ </div>
+ <div class="col-sm-2 col-xs-3 text-right">
+ Amount
+ </div>
+ </div>
{% if doc.items %}
{% for d in doc.items %}
<div class="cart-item">
- <div class="row">
- <div class="col-sm-8 col-xs-6">
- {{ item_name_and_description(d) }}
- </div>
- <div class="col-sm-4 col-xs-6 text-right">
- <div class="item-update-cart">
- <div class="clearfix">
- <input type="text" placeholder="Qty"
- style="max-width: 60px"
- value="{{ d.qty }}"
- data-item-code="{{ d.item_code }}"
- class="text-right form-control pull-right">
- </div>
- <div class="text-right">
- <button class="btn btn-default btn-sm"
- data-item-code="{{ d.item_code }}">
- </button>
- </div>
- </div>
- <p class="text-muted small" style="margin-top: 10px;">
- {{ _("Rate") + ': ' + d.get_formatted("rate") }}
- </p>
- <small style="margin-top: 10px;">
- {{ d.get_formatted("amount") }}</small>
- </div>
- </div>
+ {% include "templates/includes/cart/cart_item_line.html" %}
</div>
{% endfor %}
{% else %}
<p>{{ _("Cart is Empty") }}</p>
{% endif %}
</div>
- <div id="cart-taxes">
- </div>
+ {% if doc.items %}
+ <!-- taxes -->
+ <div class="cart-taxes row small">
+ <div class="col-sm-8"><!-- empty --></div>
+ <div class="col-sm-4">
+ {% include "templates/includes/order/order_taxes.html" %}
+ </div>
+ </div>
<div id="cart-totals">
</div>
- <div id="cart-addresses">
- <div class="row">
- <div class="col-md-6">
- <h4>{{ _("Shipping Address") }}</h4>
- <div id="cart-shipping-address" class="panel-group"
- data-fieldname="shipping_address_name"></div>
- <button class="btn btn-default btn-sm" type="button" id="cart-add-shipping-address">
- {{ _("Manage Addresses") }}</button>
- </div>
- <div class="col-md-6">
- <h4>Billing Address</h4>
- <div id="cart-billing-address" class="panel-group"
- data-fieldname="customer_address"></div>
- <button class="btn btn-default btn-sm" type="button" id="cart-add-billing-address">
- {{ _("Manage Addresses") }}</button>
- </div>
- </div>
+ <div class="cart-addresses">
+ {% include "templates/includes/cart/cart_address.html" %}
</div>
<p class="cart-footer text-right">
<button class="btn btn-primary btn-place-order btn-sm" type="button">
{{ _("Place Order") }}</button></p>
- </div>
+ {% endif %}
</div>
</div>
diff --git a/erpnext/templates/pages/cart.py b/erpnext/templates/pages/cart.py
index bb8645d..c57d826 100644
--- a/erpnext/templates/pages/cart.py
+++ b/erpnext/templates/pages/cart.py
@@ -10,5 +10,3 @@
def get_context(context):
context.update(get_cart_quotation())
-
- print context
diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html
index c3bca5b..7376392 100644
--- a/erpnext/templates/pages/order.html
+++ b/erpnext/templates/pages/order.html
@@ -3,11 +3,11 @@
<!-- <h6 class="text-muted">{{ doc._title or doc.doctype }}</h6> -->
{% endblock %}
-{% block style %}{% include "templates/includes/order.css" %}{% endblock %}
+{% block style %}{% include "templates/includes/order/order.css" %}{% endblock %}
{% block content %}
-{% from "erpnext/templates/includes/macros.html" import item_name_and_description %}
+{% from "erpnext/templates/includes/order/order_macros.html" import item_name_and_description %}
<div class="row">
<div class="col-xs-6">
@@ -64,25 +64,7 @@
<div class="order-taxes row small">
<div class="col-sm-8"><!-- empty --></div>
<div class="col-sm-4">
- {% if doc.taxes %}
- <div class="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">
- <div class="col-xs-6 text-right">{{ d.description }}</div>
- <div class="col-xs-6 text-right">
- {{ d.get_formatted("total") }}</div>
- </div>
- {% endfor %}
- <div class="row">
- <div class="col-xs-6 text-right">{{ _("Grand Total") }}</div>
- <div class="col-xs-6 text-right">
- {{ doc.get_formatted("grand_total") }}</div>
- </div>
+ {% include "erpnext/templates/includes/order/order_taxes.html" %}
</div>
</div>
</div>
diff --git a/erpnext/templates/pages/order.py b/erpnext/templates/pages/order.py
index 260490d..36444d1 100644
--- a/erpnext/templates/pages/order.py
+++ b/erpnext/templates/pages/order.py
@@ -9,6 +9,9 @@
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"):