[design] pos

This commit is contained in:
Rushabh Mehta 2014-12-19 16:20:32 +05:30 committed by Anand Doshi
parent f870527e7c
commit a9ba5eff99
26 changed files with 228 additions and 235 deletions

View File

@ -8,7 +8,6 @@ cur_frm.cscript.other_fname = "other_charges";
frappe.provide("erpnext.accounts"); frappe.provide("erpnext.accounts");
{% include 'buying/doctype/purchase_common/purchase_common.js' %}; {% include 'buying/doctype/purchase_common/purchase_common.js' %};
{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %} {% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %}
{% include 'accounts/doctype/sales_invoice/pos.js' %}
erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
onload: function() { onload: function() {

View File

@ -11,7 +11,6 @@ cur_frm.pformat.print_heading = 'Invoice';
{% include 'selling/sales_common.js' %}; {% include 'selling/sales_common.js' %};
{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %} {% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %}
{% include 'accounts/doctype/sales_invoice/pos.js' %}
frappe.provide("erpnext.accounts"); frappe.provide("erpnext.accounts");
erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.extend({ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.extend({

View File

@ -13,7 +13,7 @@ pscript['onload_Accounts Browser'] = function(wrapper){
single_column: true single_column: true
}) })
wrapper.appframe.add_module_icon("Accounts"); frappe.add_breadcrumbs("Accounts");
var main = $(wrapper).find(".layout-main"), var main = $(wrapper).find(".layout-main"),
chart_area = $("<div>") chart_area = $("<div>")

View File

@ -10,7 +10,7 @@ frappe.pages['financial-analytics'].onload = function(wrapper) {
single_column: true single_column: true
}); });
erpnext.trial_balance = new erpnext.FinancialAnalytics(wrapper, 'Financial Analytics'); erpnext.trial_balance = new erpnext.FinancialAnalytics(wrapper, 'Financial Analytics');
wrapper.appframe.add_module_icon("Accounts") frappe.add_breadcrumbs("Accounts")
} }

View File

@ -9,7 +9,6 @@ cur_frm.cscript.other_fname = "other_charges";
{% include 'buying/doctype/purchase_common/purchase_common.js' %}; {% include 'buying/doctype/purchase_common/purchase_common.js' %};
{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %} {% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %}
{% include 'accounts/doctype/sales_invoice/pos.js' %}
erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({
refresh: function(doc, cdt, cdn) { refresh: function(doc, cdt, cdn) {

View File

@ -9,7 +9,6 @@ cur_frm.cscript.other_fname = "other_charges";
// attach required files // attach required files
{% include 'buying/doctype/purchase_common/purchase_common.js' %}; {% include 'buying/doctype/purchase_common/purchase_common.js' %};
{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %} {% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %}
{% include 'accounts/doctype/sales_invoice/pos.js' %}
erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
refresh: function() { refresh: function() {

View File

@ -11,7 +11,7 @@ frappe.pages['purchase-analytics'].onload = function(wrapper) {
new erpnext.PurchaseAnalytics(wrapper); new erpnext.PurchaseAnalytics(wrapper);
wrapper.appframe.add_module_icon("Buying") frappe.add_breadcrumbs("Buying")
} }

View File

@ -73,9 +73,7 @@ class StatusUpdater(Document):
frappe.db.set_value(self.doctype, self.name, "status", self.status) frappe.db.set_value(self.doctype, self.name, "status", self.status)
def validate_qty(self): def validate_qty(self):
""" """Validates qty at row level"""
Validates qty at row level
"""
self.tolerance = {} self.tolerance = {}
self.global_tolerance = None self.global_tolerance = None
@ -153,7 +151,7 @@ class StatusUpdater(Document):
args['second_source_condition'] = "" args['second_source_condition'] = ""
if args.get('second_source_dt') and args.get('second_source_field') \ if args.get('second_source_dt') and args.get('second_source_field') \
and args.get('second_join_field'): and args.get('second_join_field'):
if not args.get("second_source_extra_cond"): if not args.get("second_source_extra_cond"):
args["second_source_extra_cond"] = "" args["second_source_extra_cond"] = ""
args['second_source_condition'] = """ + ifnull((select sum(%(second_source_field)s) args['second_source_condition'] = """ + ifnull((select sum(%(second_source_field)s)

View File

@ -13,7 +13,10 @@
"public/js/queries.js", "public/js/queries.js",
"public/js/utils/party.js", "public/js/utils/party.js",
"public/js/templates/address_list.html", "public/js/templates/address_list.html",
"public/js/templates/contact_list.html" "public/js/templates/contact_list.html",
"public/js/pos/pos.html",
"public/js/pos/pos_bill_item.html",
"public/js/pos/pos.js"
], ],
"css/shopping-cart-web.css": [ "css/shopping-cart-web.css": [
"public/css/shopping_cart.css" "public/css/shopping_cart.css"

View File

@ -20,6 +20,9 @@
} }
/* pos */ /* pos */
.pos {
}
.pos-item { .pos-item {
height: 200px; height: 200px;
overflow: hidden; overflow: hidden;
@ -28,10 +31,62 @@
padding-right: 5px !important; padding-right: 5px !important;
} }
.pos-bill { .pos-item-area {
margin-left: -30px; border: 1px solid #d1d8dd;
margin-top: -10px; border-top: none;
padding: 20px 10px; }
border-right: 1px solid #c7c7c7;
border-bottom: 1px solid #c7c7c7; .pos-item-toolbar {
padding: 10px 0px;
border-bottom: 1px solid #d1d8dd;
}
.item-list-area {
padding: 15px;
}
.pos-toolbar, .pos-bill-toolbar {
padding: 10px 0px;
border-bottom: 1px solid #d1d8dd;
height: 55px;
}
.pos-item-toolbar .form-group {
margin-bottom: 0px;
}
.pos-bill-wrapper {
border: 1px solid #d1d8dd;
border-top: none;
border-right: none;
}
.pos-bill {
margin-left: -15px;
margin-right: -15px;
}
.pos-bill-row {
margin: 0px;
padding: 7px 0px;
border-top: 1px solid #d1d8dd;
}
.pos-bill-header {
border: none !important;
background-color: #f5f7fa;
}
.pos-item-qty {
display: inline-block;
}
.pos-qty-row > div {
padding: 5px 0px;
}
.pos-qty-btn {
margin-top: 5px;
cursor: pointer;
font-size: 120%;
} }

View File

@ -7,14 +7,7 @@ frappe.provide('erpnext');
$(document).bind('toolbar_setup', function() { $(document).bind('toolbar_setup', function() {
frappe.app.name = "ERPNext"; frappe.app.name = "ERPNext";
$('.navbar-brand').html('<i class="icon-home"></i>') $('.navbar-brand').html('ERPNext');
.attr("title", "Home")
.addClass("navbar-icon-home")
.css({
"max-width": "200px",
"text-overflow": "ellipsis",
"white-space": "nowrap"
});
$('[data-link="docs"]').attr("href", "https://erpnext.com/user-guide") $('[data-link="docs"]').attr("href", "https://erpnext.com/user-guide")
}); });

View File

@ -0,0 +1,55 @@
<div class="pos">
<div class="row">
<div class="col-sm-5 pos-bill-wrapper">
<div class="pos-bill-toolbar row">
<div class="party-area col-xs-6"></div>
<div class="col-xs-6">
<button class="btn btn-success make-payment">{%= __("Pay") %}</button>
</div>
</div>
<div class="pos-bill">
<div class="item-cart">
<div class="row pos-bill-row pos-bill-header">
<div class="col-xs-5"><h6>{%= __("Item") %}</h6></div>
<div class="col-xs-4"><h6 class="text-right">{%= __("Quantity") %}</h6></div>
<div class="col-xs-3"><h6 class="text-right">{%= __("Rate") %}</h6></div>
</div>
<div class="items"></div>
</div>
<div class="totals-area">
<div class="row pos-bill-row net-total-area">
<div class="col-xs-6"><h6 class="text-muted">{%= __("Net Total") %}</h6></div>
<div class="col-xs-6"><h6 class="net-total text-right"></h6></div>
</div>
<div class="tax-table hide">
<h6>{%= __("Taxes") %}</h6>
</div>
<div class="row pos-bill-row discount-amount-area">
<div class="col-xs-6"><h6 class="text-muted">{%= __("Discount Amount") %}</h6></div>
<div class="col-xs-6"><input type="text" class="form-control discount-amount text-right"></div>
</div>
<div class="row pos-bill-row grand-total-area">
<div class="col-xs-6"><h6>{%= __("Grand Total") %}</h6></div>
<div class="col-xs-6"><h6 class="grand-total text-right"></h6></div>
</div>
<div class="row pos-bill-row paid-amount-area">
<div class="col-xs-6"><h6 class="text-muted">{%= __("Amount Paid") %}</h6></div>
<div class="col-xs-6"><input type="text" class="form-control paid-amount text-right"></div>
</div>
</div>
</div>
</div>
<div class="col-sm-7 pos-item-area">
<div class="row pos-item-toolbar">
<div class="barcode-area col-xs-4"></div>
<div class="search-area col-xs-4"></div>
<div class="item-group-area col-xs-4"></div>
</div>
<div class="item-list-area row">
<div class="col-sm-12">
<div class="row item-list"></div>
</div>
</div>
</div>
</div>
</div>

View File

@ -5,105 +5,7 @@ erpnext.POS = Class.extend({
init: function(wrapper, frm) { init: function(wrapper, frm) {
this.wrapper = wrapper; this.wrapper = wrapper;
this.frm = frm; this.frm = frm;
this.wrapper.html('<div class="container">\ this.wrapper.html(frappe.render_template("pos", {}));
<div class="row" style="margin: -9px 0px 10px -30px; border-bottom: 1px solid #c7c7c7;">\
<div class="party-area col-sm-3 col-xs-6"></div>\
<div class="barcode-area col-sm-3 col-xs-6"></div>\
<div class="search-area col-sm-3 col-xs-6"></div>\
<div class="item-group-area col-sm-3 col-xs-6"></div>\
</div>\
<div class="row">\
<div class="col-sm-6">\
<div class="pos-bill">\
<div class="item-cart">\
<table class="table table-condensed table-hover" id="cart" style="table-layout: fixed;">\
<thead>\
<tr>\
<th style="width: 40%">'+__("Item")+'</th>\
<th style="width: 9%"></th>\
<th style="width: 22%; text-align: right;">Qty</th>\
<th style="width: 9%"></th>\
<th style="width: 20%; text-align: right;">Rate</th>\
</tr>\
</thead>\
<tbody>\
</tbody>\
</table>\
</div>\
<br>\
<div class="totals-area" style="margin-left: 40%;">\
<div class="net-total-area">\
<table class="table table-condensed">\
<tr>\
<td><b>'+__("Net Total")+'</b></td>\
<td style="text-align: right;" class="net-total"></td>\
</tr>\
</table>\
</div>\
<div class="tax-table" style="display: none;">\
<table class="table table-condensed">\
<thead>\
<tr>\
<th style="width: 60%">'+__("Taxes")+'</th>\
<th style="width: 40%; text-align: right;"></th>\
</tr>\
</thead>\
<tbody>\
</tbody>\
</table>\
</div>\
<div class="discount-amount-area">\
<table class="table table-condensed">\
<tr>\
<td style="vertical-align: middle;" width="50%"><b>'+__("Discount Amount")+'</b></td>\
<td width="20%"></td>\
<td style="text-align: right;">\
<input type="text" class="form-control discount-amount" \
style="text-align: right;">\
</td>\
</tr>\
</table>\
</div>\
<div class="grand-total-area">\
<table class="table table-condensed">\
<tr>\
<td style="vertical-align: middle;"><b>'+__("Grand Total")+'</b></td>\
<td style="text-align: right; font-size: 200%; \
font-size: bold;" class="grand-total"></td>\
</tr>\
</table>\
</div>\
<div class="paid-amount-area">\
<table class="table table-condensed">\
<tr>\
<td style="vertical-align: middle;">'+__("Amount Paid")+'</td>\
<td style="text-align: right; \
font-size: bold;" class="paid-amount"></td>\
</tr>\
</table>\
</div>\
</div>\
</div>\
<br><br>\
<div class="row">\
<div class="col-sm-9">\
<button class="btn btn-success btn-lg make-payment">\
<i class="icon-money"></i> '+__("Make Payment")+'</button>\
</div>\
<div class="col-sm-3">\
<button class="btn btn-default btn-lg remove-items" style="display: none;">\
<i class="icon-trash"></i> '+__("Del")+'</button>\
</div>\
</div>\
<br><br>\
</div>\
<div class="col-sm-6">\
<div class="item-list-area">\
<div class="col-sm-12">\
<div class="row item-list"></div></div>\
</div>\
</div>\
</div></div>');
this.check_transaction_type(); this.check_transaction_type();
this.make(); this.make();
@ -271,14 +173,8 @@ erpnext.POS = Class.extend({
// if form is local then allow this function // if form is local then allow this function
$(me.wrapper).find("div.pos-item").on("click", function() { $(me.wrapper).find("div.pos-item").on("click", function() {
if(me.frm.doc.docstatus==0) { if(me.frm.doc.docstatus==0) {
if(!me.frm.doc[me.party.toLowerCase()] && ((me.frm.doctype == "Quotation" && console.log($(this).attr("data-item_code"));
me.frm.doc.quotation_to == "Customer") me.add_to_cart($(this).attr("data-item_code"));
|| me.frm.doctype != "Quotation")) {
msgprint(__("Please select {0} first.", [me.party]));
return;
}
else
me.add_to_cart($(this).attr("data-item_code"));
} }
}); });
} }
@ -288,8 +184,15 @@ erpnext.POS = Class.extend({
var me = this; var me = this;
var caught = false; var caught = false;
if(!me.frm.doc[me.party.toLowerCase()] && ((me.frm.doctype == "Quotation" &&
me.frm.doc.quotation_to == "Customer")
|| me.frm.doctype != "Quotation")) {
msgprint(__("Please select {0} first.", [me.party]));
return;
}
// get no_of_items // get no_of_items
var no_of_items = me.wrapper.find("#cart tbody tr").length; var no_of_items = me.wrapper.find(".pos-bill-item").length;
// check whether the item is already added // check whether the item is already added
if (no_of_items != 0) { if (no_of_items != 0) {
@ -333,6 +236,7 @@ erpnext.POS = Class.extend({
} }
}, },
update_qty: function(item_code, qty) { update_qty: function(item_code, qty) {
console.log([item_code, qty]);
var me = this; var me = this;
$.each(this.frm.doc[this.frm.cscript.fname] || [], function(i, d) { $.each(this.frm.doc[this.frm.cscript.fname] || [], function(i, d) {
if (d.item_code == item_code) { if (d.item_code == item_code) {
@ -368,7 +272,7 @@ erpnext.POS = Class.extend({
// If quotation to is not Customer then remove party // If quotation to is not Customer then remove party
if (this.frm.doctype == "Quotation" && this.frm.doc.quotation_to!="Customer") { if (this.frm.doctype == "Quotation" && this.frm.doc.quotation_to!="Customer") {
this.party_field.$wrapper.remove(); this.party_field.$input.prop("disabled", true);
} }
}, },
refresh_item_list: function() { refresh_item_list: function() {
@ -381,45 +285,20 @@ erpnext.POS = Class.extend({
}, },
show_items_in_item_cart: function() { show_items_in_item_cart: function() {
var me = this; var me = this;
var $items = this.wrapper.find("#cart tbody").empty(); var $items = this.wrapper.find(".items").empty();
$.each(this.frm.doc[this.frm.cscript.fname] || [], function(i, d) { $.each(this.frm.doc[this.frm.cscript.fname] || [], function(i, d) {
$(frappe.render_template("pos_bill_item", {
$(repl('<tr id="%(item_code)s" data-selected="false">\ item_code: d.item_code,
<td>%(item_code)s%(item_name)s</td>\ item_name: d.item_name===d.item_code ? "" : ("<br>" + d.item_name),
<td style="vertical-align:top; padding-top: 10px;" \ qty: d.qty,
align="right">\ actual_qty: d.actual_qty,
<div class="decrease-qty" style="cursor:pointer;">\ rate: format_currency(d.rate, me.frm.doc.currency),
<i class="icon-minus-sign icon-large text-danger"></i>\ amount: format_currency(d.amount, me.frm.doc.currency)
</div>\ })).appendTo($items);
</td>\
<td style="vertical-align:middle;">\
<input type="text" value="%(qty)s" \
class="form-control qty" style="text-align: right;">\
<div class="actual-qty small text-muted">'
+__("Stock: ")+'<span class="text-success">%(actual_qty)s</span>%(projected_qty)s</div>\
</td>\
<td style="vertical-align:top; padding-top: 10px;">\
<div class="increase-qty" style="cursor:pointer;">\
<i class="icon-plus-sign icon-large text-success"></i>\
</div>\
</td>\
<td style="text-align: right;"><b>%(amount)s</b><br>%(rate)s</td>\
</tr>',
{
item_code: d.item_code,
item_name: d.item_name===d.item_code ? "" : ("<br>" + d.item_name),
qty: d.qty,
actual_qty: d.actual_qty,
projected_qty: d.projected_qty ? (" <span title='"+__("Projected Qty")
+"'>(" + d.projected_qty + ")<span>") : "",
rate: format_currency(d.rate, me.frm.doc.currency),
amount: format_currency(d.amount, me.frm.doc.currency)
}
)).appendTo($items);
}); });
this.wrapper.find("input.qty").on("focus", function() { this.wrapper.find("input.pos-item-qty").on("focus", function() {
$(this).select(); $(this).select();
}); });
}, },
@ -461,15 +340,15 @@ erpnext.POS = Class.extend({
var me = this; var me = this;
// append quantity to the respective item after change from input box // append quantity to the respective item after change from input box
$(this.wrapper).find("input.qty").on("change", function() { $(this.wrapper).find("input.pos-item-qty").on("change", function() {
var item_code = $(this).closest("tr").attr("id"); var item_code = $(this).closest("tr").attr("id");
me.update_qty(item_code, $(this).val()); me.update_qty(item_code, $(this).val());
}); });
// increase/decrease qty on plus/minus button // increase/decrease qty on plus/minus button
$(this.wrapper).find(".increase-qty, .decrease-qty").on("click", function() { $(this.wrapper).find(".pos-qty-btn").on("click", function() {
var tr = $(this).closest("tr"); var $item = $(this).parents(".pos-bill-item:first");
me.increase_decrease_qty(tr, $(this).attr("class")); me.increase_decrease_qty($item, $(this).attr("data-action"));
}); });
// on td click toggle the highlighting of row // on td click toggle the highlighting of row
@ -487,15 +366,19 @@ erpnext.POS = Class.extend({
}); });
me.refresh_delete_btn(); me.refresh_delete_btn();
//me.focus();
},
focus: function() {
if(me.frm.doc[this.party]) { if(me.frm.doc[this.party]) {
this.barcode.$input.focus(); this.barcode.$input.focus();
} else { } else {
this.party_field.$input.focus(); if(!(this.frm.doctype == "Quotation" && this.frm.doc.quotation_to!="Customer"))
this.party_field.$input.focus();
} }
}, },
increase_decrease_qty: function(tr, operation) { increase_decrease_qty: function($item, operation) {
var item_code = tr.attr("id"); var item_code = $item.attr("data-item-code");
var item_qty = cint(tr.find("input.qty").val()); var item_qty = cint($item.find("input.pos-item-qty").val());
if (operation == "increase-qty") if (operation == "increase-qty")
this.update_qty(item_code, item_qty + 1); this.update_qty(item_code, item_qty + 1);
@ -506,7 +389,7 @@ erpnext.POS = Class.extend({
var me = this; var me = this;
// if form is submitted & cancelled then disable all input box & buttons // if form is submitted & cancelled then disable all input box & buttons
$(this.wrapper) $(this.wrapper)
.find(".remove-items, .make-payment, .increase-qty, .decrease-qty") .find(".remove-items, .make-payment, .pos-qty-btn")
.toggle(this.frm.doc.docstatus===0); .toggle(this.frm.doc.docstatus===0);
$(this.wrapper).find('input, button').prop("disabled", !(this.frm.doc.docstatus===0)); $(this.wrapper).find('input, button').prop("disabled", !(this.frm.doc.docstatus===0));

View File

@ -0,0 +1,16 @@
<div class="row pos-bill-row pos-bill-item" data-item-code="{%= item_code %}">
<div class="col-xs-5"><h6>{%= item_code %}{%= item_name %}</h6></div>
<div class="col-xs-4">
<div class="row pos-qty-row">
<div class="col-xs-2 text-center pos-qty-btn" data-action="decrease-qty"><i class="icon-minus-sign text-muted"></i></div>
<div class="col-xs-8">
<input type="text" value="{%= qty %}" class="form-control input-sm pos-item-qty text-right">
<div class="actual-qty small text-muted text-right">{%= actual_qty %}</div>
</div>
<div class="col-xs-2 text-center pos-qty-btn" data-action="increase-qty"><i class="icon-plus-sign text-muted"></i></div>
</div>
</div>
<div class="col-xs-3 text-right">
<h6>{%= amount %}<div class="text-muted" style="margin-top: 5px;">{%= rate %}</div></h6>
</div>
</div>

View File

@ -105,12 +105,12 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
// make pos // make pos
if(!this.frm.pos) { if(!this.frm.pos) {
this.frm.layout.add_view("pos"); var wrapper = this.frm.appframe.add_view("pos", "<div>");
this.frm.pos = new erpnext.POS(this.frm.layout.views.pos, this.frm); this.frm.pos = new erpnext.POS(wrapper, this.frm);
} }
// toggle view // toggle view
this.frm.layout.set_view(this.pos_active ? "" : "pos"); this.frm.appframe.set_view(this.pos_active ? "main" : "pos");
this.pos_active = !this.pos_active; this.pos_active = !this.pos_active;
// refresh // refresh
@ -224,9 +224,9 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
me.frm.script_manager.trigger("currency"); me.frm.script_manager.trigger("currency");
me.apply_pricing_rule(); me.apply_pricing_rule();
} }
} }
if (this.frm.doc.posting_date) var date = this.frm.doc.posting_date; if (this.frm.doc.posting_date) var date = this.frm.doc.posting_date;
else var date = this.frm.doc.transaction_date; else var date = this.frm.doc.transaction_date;
erpnext.get_fiscal_year(this.frm.doc.company, date, fn); erpnext.get_fiscal_year(this.frm.doc.company, date, fn);

View File

@ -10,7 +10,6 @@ cur_frm.cscript.sales_team_fname = "sales_team";
{% include 'selling/sales_common.js' %} {% include 'selling/sales_common.js' %}
{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %} {% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %}
{% include 'accounts/doctype/sales_invoice/pos.js' %}
erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
onload: function(doc, dt, dn) { onload: function(doc, dt, dn) {

View File

@ -10,7 +10,6 @@ cur_frm.cscript.sales_team_fname = "sales_team";
{% include 'selling/sales_common.js' %} {% include 'selling/sales_common.js' %}
{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %} {% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %}
{% include 'accounts/doctype/sales_invoice/pos.js' %}
erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({
refresh: function(doc, dt, dn) { refresh: function(doc, dt, dn) {

View File

@ -10,7 +10,7 @@ frappe.pages['sales-analytics'].onload = function(wrapper) {
new erpnext.SalesAnalytics(wrapper); new erpnext.SalesAnalytics(wrapper);
wrapper.appframe.add_module_icon("Selling") frappe.add_breadcrumbs("Selling")
} }

View File

@ -6,7 +6,7 @@ pscript['onload_Sales Browser'] = function(wrapper){
parent: wrapper, parent: wrapper,
}) })
wrapper.appframe.add_module_icon("Selling") frappe.add_breadcrumbs("Selling")
wrapper.appframe.set_title_right(__('Refresh'), function() { wrapper.appframe.set_title_right(__('Refresh'), function() {
wrapper.make_tree(); wrapper.make_tree();

View File

@ -1,73 +1,71 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt // License: GNU General Public License v3. See license.txt
frappe.pages['sales-funnel'].onload = function(wrapper) { frappe.pages['sales-funnel'].onload = function(wrapper) {
frappe.ui.make_app_page({ frappe.ui.make_app_page({
parent: wrapper, parent: wrapper,
title: __('Sales Funnel'), title: __('Sales Funnel'),
single_column: true single_column: true
}); });
wrapper.sales_funnel = new erpnext.SalesFunnel(wrapper); wrapper.sales_funnel = new erpnext.SalesFunnel(wrapper);
wrapper.appframe.add_module_icon("Selling", "sales-funnel", function() { frappe.add_breadcrumbs("Selling");
frappe.set_route("selling-home");
});
} }
erpnext.SalesFunnel = Class.extend({ erpnext.SalesFunnel = Class.extend({
init: function(wrapper) { init: function(wrapper) {
var me = this; var me = this;
// 0 setTimeout hack - this gives time for canvas to get width and height // 0 setTimeout hack - this gives time for canvas to get width and height
setTimeout(function() { setTimeout(function() {
me.setup(wrapper); me.setup(wrapper);
me.get_data(); me.get_data();
}, 0); }, 0);
}, },
setup: function(wrapper) { setup: function(wrapper) {
var me = this; var me = this;
this.elements = { this.elements = {
layout: $(wrapper).find(".layout-main"), layout: $(wrapper).find(".layout-main"),
from_date: wrapper.appframe.add_date(__("From Date")), from_date: wrapper.appframe.add_date(__("From Date")),
to_date: wrapper.appframe.add_date(__("To Date")), to_date: wrapper.appframe.add_date(__("To Date")),
refresh_btn: wrapper.appframe.set_title_right(__("Refresh"), refresh_btn: wrapper.appframe.set_title_right(__("Refresh"),
function() { me.get_data(); }, "icon-refresh"), function() { me.get_data(); }, "icon-refresh"),
}; };
this.elements.no_data = $('<div class="alert alert-warning">' + __("No Data") + '</div>') this.elements.no_data = $('<div class="alert alert-warning">' + __("No Data") + '</div>')
.toggle(false) .toggle(false)
.appendTo(this.elements.layout); .appendTo(this.elements.layout);
this.elements.funnel_wrapper = $('<div class="funnel-wrapper text-center"></div>') this.elements.funnel_wrapper = $('<div class="funnel-wrapper text-center"></div>')
.appendTo(this.elements.layout); .appendTo(this.elements.layout);
this.options = { this.options = {
from_date: frappe.datetime.add_months(frappe.datetime.get_today(), -1), from_date: frappe.datetime.add_months(frappe.datetime.get_today(), -1),
to_date: frappe.datetime.get_today() to_date: frappe.datetime.get_today()
}; };
// set defaults and bind on change // set defaults and bind on change
$.each(this.options, function(k, v) { $.each(this.options, function(k, v) {
me.elements[k].val(frappe.datetime.str_to_user(v)); me.elements[k].val(frappe.datetime.str_to_user(v));
me.elements[k].on("change", function() { me.elements[k].on("change", function() {
me.options[k] = frappe.datetime.user_to_str($(this).val()); me.options[k] = frappe.datetime.user_to_str($(this).val());
me.get_data(); me.get_data();
}); });
}); });
// bind refresh // bind refresh
this.elements.refresh_btn.on("click", function() { this.elements.refresh_btn.on("click", function() {
me.get_data(this); me.get_data(this);
}); });
// bind resize // bind resize
$(window).resize(function() { $(window).resize(function() {
me.render(); me.render();
}); });
}, },
get_data: function(btn) { get_data: function(btn) {
var me = this; var me = this;
frappe.call({ frappe.call({
@ -85,72 +83,72 @@ erpnext.SalesFunnel = Class.extend({
} }
}); });
}, },
render: function() { render: function() {
var me = this; var me = this;
this.prepare(); this.prepare();
var context = this.elements.context, var context = this.elements.context,
x_start = 0.0, x_start = 0.0,
x_end = this.options.width, x_end = this.options.width,
x_mid = (x_end - x_start) / 2.0, x_mid = (x_end - x_start) / 2.0,
y = 0, y = 0,
y_old = 0.0; y_old = 0.0;
if(this.options.total_value === 0) { if(this.options.total_value === 0) {
this.elements.no_data.toggle(true); this.elements.no_data.toggle(true);
return; return;
} }
this.options.data.forEach(function(d) { this.options.data.forEach(function(d) {
context.fillStyle = d.color; context.fillStyle = d.color;
context.strokeStyle = d.color; context.strokeStyle = d.color;
me.draw_triangle(x_start, x_mid, x_end, y, me.options.height); me.draw_triangle(x_start, x_mid, x_end, y, me.options.height);
y_old = y; y_old = y;
// new y // new y
y = y + d.height; y = y + d.height;
// new x // new x
var half_side = (me.options.height - y) / Math.sqrt(3); var half_side = (me.options.height - y) / Math.sqrt(3);
x_start = x_mid - half_side; x_start = x_mid - half_side;
x_end = x_mid + half_side; x_end = x_mid + half_side;
var y_mid = y_old + (y - y_old) / 2.0; var y_mid = y_old + (y - y_old) / 2.0;
me.draw_legend(x_mid, y_mid, me.options.width, me.options.height, d.value + " - " + d.title); me.draw_legend(x_mid, y_mid, me.options.width, me.options.height, d.value + " - " + d.title);
}); });
}, },
prepare: function() { prepare: function() {
var me = this; var me = this;
this.elements.no_data.toggle(false); this.elements.no_data.toggle(false);
// calculate width and height options // calculate width and height options
this.options.width = $(this.elements.funnel_wrapper).width() * 2.0 / 3.0; this.options.width = $(this.elements.funnel_wrapper).width() * 2.0 / 3.0;
this.options.height = (Math.sqrt(3) * this.options.width) / 2.0; this.options.height = (Math.sqrt(3) * this.options.width) / 2.0;
// calculate total weightage // calculate total weightage
// as height decreases, area decreases by the square of the reduction // as height decreases, area decreases by the square of the reduction
// hence, compensating by squaring the index value // hence, compensating by squaring the index value
this.options.total_weightage = this.options.data.reduce( this.options.total_weightage = this.options.data.reduce(
function(prev, curr, i) { return prev + Math.pow(i+1, 2) * curr.value; }, 0.0); function(prev, curr, i) { return prev + Math.pow(i+1, 2) * curr.value; }, 0.0);
// calculate height for each data // calculate height for each data
$.each(this.options.data, function(i, d) { $.each(this.options.data, function(i, d) {
d.height = me.options.height * d.value * Math.pow(i+1, 2) / me.options.total_weightage; d.height = me.options.height * d.value * Math.pow(i+1, 2) / me.options.total_weightage;
}); });
this.elements.canvas = $('<canvas></canvas>') this.elements.canvas = $('<canvas></canvas>')
.appendTo(this.elements.funnel_wrapper.empty()) .appendTo(this.elements.funnel_wrapper.empty())
.attr("width", $(this.elements.funnel_wrapper).width()) .attr("width", $(this.elements.funnel_wrapper).width())
.attr("height", this.options.height); .attr("height", this.options.height);
this.elements.context = this.elements.canvas.get(0).getContext("2d"); this.elements.context = this.elements.canvas.get(0).getContext("2d");
}, },
draw_triangle: function(x_start, x_mid, x_end, y, height) { draw_triangle: function(x_start, x_mid, x_end, y, height) {
var context = this.elements.context; var context = this.elements.context;
context.beginPath(); context.beginPath();
@ -161,27 +159,27 @@ erpnext.SalesFunnel = Class.extend({
context.closePath(); context.closePath();
context.fill(); context.fill();
}, },
draw_legend: function(x_mid, y_mid, width, height, title) { draw_legend: function(x_mid, y_mid, width, height, title) {
var context = this.elements.context; var context = this.elements.context;
// draw line // draw line
context.beginPath(); context.beginPath();
context.moveTo(x_mid, y_mid); context.moveTo(x_mid, y_mid);
context.lineTo(width, y_mid); context.lineTo(width, y_mid);
context.closePath(); context.closePath();
context.stroke(); context.stroke();
// draw circle // draw circle
context.beginPath(); context.beginPath();
context.arc(width, y_mid, 5, 0, Math.PI * 2, false); context.arc(width, y_mid, 5, 0, Math.PI * 2, false);
context.closePath(); context.closePath();
context.fill(); context.fill();
// draw text // draw text
context.fillStyle = "black"; context.fillStyle = "black";
context.textBaseline = "middle"; context.textBaseline = "middle";
context.font = "1.1em sans-serif"; context.font = "1.1em sans-serif";
context.fillText(title, width + 20, y_mid); context.fillText(title, width + 20, y_mid);
} }
}); });

View File

@ -9,7 +9,6 @@ cur_frm.cscript.sales_team_fname = "sales_team";
{% include 'selling/sales_common.js' %}; {% include 'selling/sales_common.js' %};
{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %} {% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %}
{% include 'accounts/doctype/sales_invoice/pos.js' %}
frappe.provide("erpnext.stock"); frappe.provide("erpnext.stock");
frappe.provide("erpnext.stock.delivery_note"); frappe.provide("erpnext.stock.delivery_note");

View File

@ -7,7 +7,6 @@ cur_frm.cscript.other_fname = "other_charges";
{% include 'buying/doctype/purchase_common/purchase_common.js' %}; {% include 'buying/doctype/purchase_common/purchase_common.js' %};
{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %} {% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %}
{% include 'accounts/doctype/sales_invoice/pos.js' %}
frappe.provide("erpnext.stock"); frappe.provide("erpnext.stock");
erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend({ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend({

View File

@ -12,7 +12,7 @@ frappe.pages['stock-analytics'].onload = function(wrapper) {
new erpnext.StockAnalytics(wrapper); new erpnext.StockAnalytics(wrapper);
wrapper.appframe.add_module_icon("Stock") frappe.add_breadcrumbs("Stock")
} }

View File

@ -9,7 +9,7 @@ frappe.pages['stock-ledger'].onload = function(wrapper) {
}); });
new erpnext.StockLedger(wrapper); new erpnext.StockLedger(wrapper);
wrapper.appframe.add_module_icon("Stock") frappe.add_breadcrumbs("Stock")
} }
frappe.require("assets/erpnext/js/stock_grid_report.js"); frappe.require("assets/erpnext/js/stock_grid_report.js");

View File

@ -11,7 +11,7 @@ frappe.pages['stock-level'].onload = function(wrapper) {
new erpnext.StockLevel(wrapper); new erpnext.StockLevel(wrapper);
wrapper.appframe.add_module_icon("Stock") frappe.add_breadcrumbs("Stock")
; ;
} }

View File

@ -11,7 +11,7 @@ frappe.pages['support-analytics'].onload = function(wrapper) {
new erpnext.SupportAnalytics(wrapper); new erpnext.SupportAnalytics(wrapper);
wrapper.appframe.add_module_icon("Support") frappe.add_breadcrumbs("Support")
} }