[cleanup] [wip] portal, shopping cart cleanup

This commit is contained in:
Rushabh Mehta 2015-09-11 18:49:59 +05:30
parent 65b6762247
commit 156ce607e2
20 changed files with 395 additions and 190 deletions

View File

@ -21,37 +21,54 @@ def get_list_context(context=None):
def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20):
from frappe.templates.pages.list import get_list
user = frappe.session.user
key = None
if not filters: filters = []
filters.append((doctype, "docstatus", "=", 1))
if user != "Guest" and is_website_user():
# find party for this contact
customers, suppliers = get_customers_suppliers(doctype, user)
if customers:
return post_process(get_list(doctype, txt, filters=[(doctype, "customer", "in", customers)],
limit_start=limit_start, limit_page_length=limit_page_length, ignore_permissions=True))
key, parties = "customer", customers
elif suppliers:
return post_process(get_list(doctype, txt, filters=[(doctype, "supplier", "in", suppliers)],
limit_start=limit_start, limit_page_length=limit_page_length, ignore_permissions=True))
key, parties = "supplier", suppliers
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:
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):
for r in result:
r.status_percent = 0
r.status_display = []
def post_process(doctype, data):
result = []
for d in data:
doc = frappe.get_doc(doctype, d.name)
if r.get("per_billed"):
r.status_percent += flt(r.per_billed)
r.status_display.append(_("Billed") if r.per_billed==100 else _("{0}% Billed").format(r.per_billed))
doc.status_percent = 0
doc.status_display = []
if r.get("per_delivered"):
r.status_percent += flt(r.per_delivered)
r.status_display.append(_("Delivered") if r.per_delivered==100 else _("{0}% Delivered").format(r.per_delivered))
if doc.get("per_billed"):
doc.status_percent += flt(doc.per_billed)
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))
doc.status_display = ", ".join(doc.status_display)
doc.items_preview = ", ".join([d.item_name for d in doc.items])
result.append(doc)
return result

View File

@ -1,4 +1,6 @@
from __future__ import unicode_literals
from frappe import _
app_name = "erpnext"
app_title = "ERPNext"
app_publisher = "Frappe Technologies Pvt. Ltd."
@ -62,11 +64,26 @@ website_context = {
website_route_rules = [
{"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/<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/<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 = {

View File

@ -29,6 +29,7 @@
background-repeat: no-repeat;
background-position: center top;
border-radius: 0.5em;
border: 1px solid #ebeff2;
}
.product-image.missing-image {
width: 100%;
@ -38,6 +39,7 @@
background-repeat: no-repeat;
background-position: center top;
border-radius: 0.5em;
border: 1px solid #ebeff2;
border: 1px dashed #d1d8dd;
position: relative;
}

View File

@ -1,4 +1,5 @@
@border-color: #d1d8dd;
@light-border-color: #EBEFF2;
.web-long-description {
font-size: 18px;
@ -35,6 +36,7 @@
background-repeat: no-repeat;
background-position: center top;
border-radius: 0.5em;
border: 1px solid @light-border-color;
}
.product-image.missing-image {

View File

@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe import throw, _
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.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import get_shopping_cart_settings
from frappe.utils.nestedset import get_root_of
@ -134,20 +134,10 @@ def guess_territory():
frappe.db.get_value("Shopping Cart Settings", None, "territory") or \
get_root_of("Territory")
def decorate_quotation_doc(quotation_doc):
doc = frappe._dict(quotation_doc.as_dict())
def decorate_quotation_doc(doc):
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))
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
@ -314,7 +304,6 @@ def get_address_docs(doctype=None, txt=None, filters=None, limit_start=0, limit_
for address in address_docs:
address.display = get_address_display(address)
address.display = (address.display).replace("\n", "<br>\n")
return address_docs

View File

@ -19,6 +19,7 @@ class Item(WebsiteGenerator):
condition_field = "show_in_website",
template = "templates/generators/item.html",
parent_website_route_field = "item_group",
no_cache = 1
)
def onload(self):

View File

@ -27,19 +27,28 @@
{{ _("Item Code") }}: <span itemprop="productID">{{ name }}</span></p>
<br>
<div style="min-height: 100px; margin: 10px 0;">
<div class="item-price-info" style="display: none;">
<h4 class="item-price" itemprop="price"></h4>
<div class="item-stock" itemprop="availablity"></div>
<div class="item-cart hide">
<div id="item-add-to-cart">
<button class="btn btn-primary">
<i class="icon-shopping-cart"></i> + {{ _("Add to Cart") }}</button>
<button class="btn btn-primary btn-sm">
{{ _("Add to Cart") }}</button>
</div>
<div id="item-update-cart" class="input-group col-md-4" style="display: none;
padding-left: 0px; padding-right: 0px;">
<input class="form-control" type="text">
<div class="input-group-btn">
<button class="btn btn-primary">
<i class="icon-ok"></i></button>
<div id="item-update-cart"
style="display: none;
padding-left: 0px; padding-right: 0px;
padding-top: 10px;">
<div>
<input class="form-control"
type="text" style="max-width: 140px;">
</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>

View File

@ -1,19 +1,8 @@
<div class="web-list-item">
<a href="/addresses?name={{ doc.name }}" no-pjax>
<div class="row">
<div class="col-sm-4">
<span class="strong">{{ doc.address_title }}</span>
</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 }}
<a href="/addresses?name={{ doc.name }}" no-pjax class="no-decoration">
<h4 class="strong">{{ doc.address_title }}</h4>
<p class="text-muted small">
{{ frappe.get_doc(doc).get_display() }}
</div>
</div>
</a>

View File

@ -0,0 +1,7 @@
.cart-content {
min-height: 400px;
}
.cart-header, .cart-footer {
margin-bottom: 40px;
}

View File

@ -92,12 +92,12 @@ $.extend(shopping_cart, {
$('<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>"
description: "",
formatted_tax_amount: __("Total") + ": <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>');
$cart_shipping_address.html('<p>'+frappe._("Please add a new address")+'</p>');
} else {
shopping_cart.render_address($cart_shipping_address, addresses, doc.shipping_address_name);
shopping_cart.render_address($cart_billing_address, addresses, doc.customer_address);
@ -113,9 +113,9 @@ $.extend(shopping_cart, {
$(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>\
<div class="col-md-2">%(image_html)s</div>\
<div class="col-md-10">\
<h5><a href="%(page_name)s">%(item_name)s</a></h5>\
<p>%(description)s</p>\
</div>\
</div>\
@ -129,8 +129,8 @@ $.extend(shopping_cart, {
<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>\
<p class="text-muted small" style="margin-top: 10px;">' + __("Rate") + ': %(formatted_rate)s</p>\
<small style="margin-top: 10px;">%(formatted_amount)s</small>\
</div>\
</div><hr>', doc)).appendTo($cart_items);
},
@ -189,12 +189,12 @@ $.extend(shopping_cart, {
<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" \
<div class="col-md-2 text-right"><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 class="panel-body text-muted small">%(display)s</div> \
</div> \
</div>', address))
.css({"margin": "10px auto"})
@ -274,24 +274,24 @@ $.extend(shopping_cart, {
$(document).ready(function() {
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);
}
}
});
// return frappe.call({
// type: "POST",
// method: "erpnext.shopping_cart.cart.get_cart_quotation",
// callback: function(r) {
// $("#cart-container").removeClass("hide");
// $(".loading").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);
// }
// }
// });
});

View File

@ -1,21 +1,15 @@
<div class="web-list-item">
<div class="row">
<div class="col-sm-6">
<a class="no-decoration" href="/issues?name={{ doc.name }}" no-pjax>
{{ doc.subject }}
</a>
</div>
<div class="col-sm-2">
<div class="row">
<div class="col-xs-8">
<span class="indicator {{ "red" if doc.status=="Open" else "blue" }}">
{{ doc.status }}</span>
{{ doc.name }}</span>
<span style="margin-left: 15px;">
{{ doc.subject }}</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">
<div class="col-xs-4 text-right small">
{{ frappe.format_date(doc.creation) }}
</div>
</div>
</a>
</div>

View File

@ -14,3 +14,17 @@
{%- endif %}
</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 %}

View 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;
}

View File

@ -1,7 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
$(document).ready(function() {
frappe.ready(function() {
var item_code = $('[itemscope] [itemprop="productID"]').text().trim();
var qty = 0;
@ -12,6 +12,8 @@ $(document).ready(function() {
item_code: "{{ name }}"
},
callback: function(r) {
console.log(r.message);
$(".item-cart").toggleClass("hide", !!!r.message.price);
if(r.message && r.message.price) {
$(".item-price")
.html(r.message.price.formatted_price + " per " + r.message.uom);
@ -24,12 +26,11 @@ $(document).ready(function() {
<i class='icon-check'></i> Available (in stock)</div>");
}
$(".item-price-info").toggle(true);
if(r.message.qty) {
qty = r.message.qty;
toggle_update_cart(qty);
$("#item-update-cart input").val(qty);
toggle_update_cart(r.message.qty);
} else {
toggle_update_cart(0);
}
}
}

View File

@ -1,29 +1,22 @@
{% set doc = frappe.get_doc(doc) %}
<div class="web-list-item">
<a href="/{{ pathname }}/{{ doc.name }}" no-pjax>
<div class="row">
<div class="col-sm-6 col-xs-7">
<div class="col-sm-8 col-xs-7">
<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">
{%- if doc.status_percent > 0 -%}
{%- if doc.status_percent % 100 == 0 -%}
<span class="indicator green">{{ doc.status_display }}</span>
{%- else -%}
<span class="indicator orange">{{ doc.status_display }}</span>
{%- endif -%}
{%- elif doc.status -%}
<span class="indicator blue">{{ doc.status }}</span>
{%- endif -%}
<span class="indicator {{ doc.indicator_color or "darkgrey" }}">
{{ doc.indicator_title or doc.status or "Submitted" }}
</span>
</div>
</div>
</div>
<div class="col-sm-2 col-xs-5 text-right">
{{ doc.get_formatted("grand_total") }}
</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") }}">
{{ frappe.utils.pretty_date(doc.creation) }}</div>
</div>

View File

@ -3,54 +3,85 @@
{% block header %}<h2>{{ _("My Cart") }}</h2>{% endblock %}
{% block script %}{% include "templates/includes/cart.js" %}{% endblock %}
{% block style %}{% include "templates/includes/cart.css" %}{% endblock %}
{% block content %}
{% from "erpnext/templates/includes/macros.html" import item_name_and_description %}
<div class="cart-content">
<div class="text-muted progress">{{ _("Loading") }}...</div>
<div id="cart-container" class="hide">
<p class="pull-right"><button class="btn btn-success btn-place-order" type="button">
<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>
<hr>
<div class="row">
<div class="col-md-9 col-sm-9">
<div class="row">
<div class="col-md-9 col-md-offset-3"><h4>{{ _("Item Details") }}</h4></div>
</div>
</div>
<div class="col-md-3 col-sm-3 text-right"><h4>{{ _("Qty, Amount") }}</h4></div>
</div><hr>
<div id="cart-items">
{% 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>
</div>
{% endfor %}
{% else %}
<p>{{ _("Cart is Empty") }}</p>
{% endif %}
</div>
<div id="cart-taxes">
</div>
<div id="cart-totals">
</div>
<hr>
<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" type="button" id="cart-add-shipping-address">
<span class="icon icon-list"></span> {{ _("Manage Addresses") }}</button>
<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" type="button" id="cart-add-billing-address">
<span class="icon icon-list"></span> {{ _("Manage Addresses") }}</button>
<button class="btn btn-default btn-sm" type="button" id="cart-add-billing-address">
{{ _("Manage Addresses") }}</button>
</div>
</div>
<hr>
</div>
<p class="pull-right"><button class="btn btn-success btn-place-order" type="button">
<p class="cart-footer text-right">
<button class="btn btn-primary btn-place-order btn-sm" type="button">
{{ _("Place Order") }}</button></p>
</div>
</div>
</div>
<!-- no-sidebar -->
{% endblock %}

View File

@ -2,7 +2,13 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
from __future__ import unicode_literals
no_cache = 1
no_sitemap = 1
import frappe
from erpnext.shopping_cart.cart import get_cart_quotation
def get_context(context):
context.update(get_cart_quotation())
print context

View File

@ -0,0 +1,90 @@
{% block header %}
<h1>{{ doc.name }}</h1>
<!-- <h6 class="text-muted">{{ doc._title or doc.doctype }}</h6> -->
{% endblock %}
{% block style %}{% include "templates/includes/order.css" %}{% endblock %}
{% block content %}
{% from "erpnext/templates/includes/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">
{% 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>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,15 @@
# 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)
context.parents = frappe.form_dict.parents
if not context.doc.has_permission("read"):
frappe.throw(_("Not Permitted"), frappe.PermissionError)

View File

@ -70,6 +70,9 @@ class Address(Document):
(is_address_type, fieldname, "%s", "%s"), (self.get(fieldname), self.name))
break
def get_display(self):
return get_address_display(self.as_dict())
@frappe.whitelist()
def get_address_display(address_dict):
if not address_dict: