[fix] [minor] merged with master

This commit is contained in:
Nabin Hait 2013-08-26 16:55:42 +05:30
commit 92b0e777e8
37 changed files with 723 additions and 103 deletions

View File

@ -5,10 +5,73 @@ erpnext.POS = Class.extend({
init: function(wrapper, frm) {
this.wrapper = wrapper;
this.frm = frm;
this.wrapper.html('<div class="customer-area"></div>\
<div class="item-area"></div>\
<div><button class="btn btn-default btn-add">Add</button>');
this.wrapper.html('<div class="container">\
<div class="row">\
<div class="customer-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: 50%">Item</th>\
<th style="width: 25%; text-align: right;">Qty</th>\
<th style="width: 25%; text-align: right;">Rate</th>\
</tr>\
</thead>\
<tbody>\
</tbody>\
</table>\
</div>\
<br>\
<div class="net-total-area" style="margin-left: 40%;">\
<table class="table table-condensed">\
<tr>\
<td><b>Net Total</b></td>\
<td style="text-align: right;" class="net-total"></td>\
</tr>\
</table>\
<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>\
<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>\
<br><br>\
<button class="btn btn-success btn-lg make-payment">\
<i class="icon-money"></i> Make Payment</button>\
<button class="btn btn-default btn-lg delete-items pull-right" style="display: none;">\
<i class="icon-trash"></i> Del</button>\
<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.make();
var me = this;
@ -16,10 +79,20 @@ erpnext.POS = Class.extend({
me.refresh();
});
this.wrapper.find(".delete-items").on("click", function() {
me.remove_selected_item();
});
this.wrapper.find(".make-payment").on("click", function() {
me.make_payment();
});
},
make: function() {
this.make_customer();
this.make_items();
this.make_item_group();
this.make_search();
this.make_barcode();
this.make_item_list();
},
make_customer: function() {
var me = this;
@ -28,7 +101,8 @@ erpnext.POS = Class.extend({
"fieldtype": "Link",
"options": "Customer",
"label": "Customer",
"fieldname": "pos_customer"
"fieldname": "pos_customer",
"placeholder": "Customer"
},
parent: this.wrapper.find(".customer-area")
});
@ -36,25 +110,302 @@ erpnext.POS = Class.extend({
this.customer.$input.on("change", function() {
if(!me.customer.autocomplete_open)
wn.model.set_value("Sales Invoice", me.frm.docname, "customer", this.value);
});
},
make_items: function() {
var me = this;
this.wrapper.find(".btn-add").click(function() {
var child = wn.model.add_child(me.frm.doc, "Sales Invoice Item", "entries");
child.item_code = "Test Item";
me.frm.cscript.item_code(me.frm.doc, child.doctype, child.name);
});
},
make_item_group: function() {
var me = this;
this.item_group = wn.ui.form.make_control({
df: {
"fieldtype": "Link",
"options": "Item Group",
"label": "Item Group",
"fieldname": "pos_item_group",
"placeholder": "Filter by Item Group"
},
parent: this.wrapper.find(".item-group-area")
});
this.item_group.make_input();
this.item_group.$input.on("change", function() {
if(!me.item_group.autocomplete_open)
me.make_item_list();
});
},
make_search: function() {
var me = this;
this.search = wn.ui.form.make_control({
df: {
"fieldtype": "Link",
"options": "Item",
"label": "Item",
"fieldname": "pos_item",
"placeholder": "Select Item"
},
parent: this.wrapper.find(".search-area")
});
this.search.make_input();
this.search.$input.on("change", function() {
if(!me.search.autocomplete_open)
me.make_item_list();
});
},
make_barcode: function() {
var me = this;
this.barcode = wn.ui.form.make_control({
df: {
"fieldtype": "Data",
"label": "Barcode",
"fieldname": "pos_barcode",
"placeholder": "Select Barcode"
},
parent: this.wrapper.find(".barcode-area")
});
this.barcode.make_input();
this.barcode.$input.on("change", function() {
me.add_item_thru_barcode();
});
},
make_item_list: function() {
var me = this;
wn.call({
method: 'accounts.doctype.sales_invoice.pos.get_items',
args: {
price_list: cur_frm.doc.selling_price_list,
item_group: this.item_group.$input.val(),
item: this.search.$input.val()
},
callback: function(r) {
var $wrap = me.wrapper.find(".item-list");
me.wrapper.find(".item-list").empty();
$.each(r.message, function(index, obj) {
if (obj.image)
image = "<img src='" + obj.image + "' class='img-responsive'>";
else
image = '<div class="missing-image"><i class="icon-camera"></i></div>';
$(repl('<div class="col-xs-3 pos-item" data-item_code="%(item_code)s">\
%(item_image)s\
<div class="small">%(item_code)s</div>\
<div class="small">%(item_name)s</div>\
<div class="small">%(item_price)s</div>\
</div>',
{
item_code: obj.name,
item_price: format_currency(obj.ref_rate, obj.ref_currency),
item_name: obj.name===obj.item_name ? "" : obj.item_name,
item_image: image
})).appendTo($wrap);
});
$("div.pos-item").on("click", function() {
if(!cur_frm.doc.customer) {
msgprint("Please select customer first.");
return;
}
me.add_to_cart($(this).attr("data-item_code"));
});
}
});
},
add_to_cart: function(item_code) {
var me = this;
var caught = false;
// get no_of_items
no_of_items = me.wrapper.find("#cart tbody").length;
// check whether the item is already added
if (no_of_items != 0) {
$.each(wn.model.get_children("Sales Invoice Item", this.frm.doc.name, "entries",
"Sales Invoice"), function(i, d) {
if (d.item_code == item_code)
caught = true;
});
}
// if duplicate row then append the qty
if (caught) {
me.update_qty(item_code, 1);
}
else {
var child = wn.model.add_child(me.frm.doc, "Sales Invoice Item", "entries");
child.item_code = item_code;
me.frm.cscript.item_code(me.frm.doc, child.doctype, child.name);
//me.refresh();
}
},
update_qty: function(item_code, qty) {
var me = this;
$.each(wn.model.get_children("Sales Invoice Item", this.frm.doc.name, "entries",
"Sales Invoice"), function(i, d) {
if (d.item_code == item_code) {
if (qty == 1)
d.qty += 1;
else
d.qty = qty;
me.frm.cscript.qty(me.frm.doc, d.doctype, d.name);
}
});
me.refresh();
},
refresh: function() {
var me = this;
this.customer.set_input(this.frm.doc.customer);
this.barcode.set_input("");
// add items
var $items = me.wrapper.find(".item-area").empty();
var $items = me.wrapper.find("#cart tbody").empty();
$.each(wn.model.get_children("Sales Invoice Item", this.frm.doc.name, "entries",
"Sales Invoice"), function(i, d) {
$(repl("<div>%(item_code)s</div>", d)).appendTo($items);
$(repl('<tr id="%(item_code)s" data-selected="false">\
<td>%(item_code)s%(item_name)s</td>\
<td><input type="text" value="%(qty)s" \
class="form-control qty" style="text-align: right;"></td>\
<td style="text-align: right;">%(rate)s<br><b>%(amount)s</b></td>\
</tr>',
{
item_code: d.item_code,
item_name: d.item_name===d.item_code ? "" : ("<br>" + d.item_name),
qty: d.qty,
rate: format_currency(d.ref_rate, cur_frm.doc.price_list_currency),
amount: format_currency(d.export_amount, cur_frm.doc.price_list_currency)
}
)).appendTo($items);
});
// taxes
var taxes = wn.model.get_children("Sales Taxes and Charges", this.frm.doc.name, "other_charges",
"Sales Invoice");
$(".tax-table")
.toggle((taxes && taxes.length) ? true : false)
.find("tbody").empty();
$.each(taxes, function(i, d) {
$(repl('<tr>\
<td>%(description)s</td>\
<td style="text-align: right;">%(tax_amount)s</td>\
<tr>', {
description: d.description,
tax_amount: format_currency(d.tax_amount, me.frm.doc.price_list_currency)
})).appendTo(".tax-table tbody");
});
// set totals
this.wrapper.find(".net-total").text(format_currency(this.frm.doc.net_total_export,
cur_frm.doc.price_list_currency));
this.wrapper.find(".grand-total").text(format_currency(this.frm.doc.grand_total_export,
cur_frm.doc.price_list_currency));
// append quantity to the respective item after change from input box
$("input.qty").on("change", function() {
var item_code = $(this).closest("tr")[0].id;
me.update_qty(item_code, $(this).val());
});
// on td click highlight the respective row
$("td").on("click", function() {
var row = $(this).closest("tr");
if (row.attr("data-selected") == "false") {
row.attr("class", "warning");
row.attr("data-selected", "true");
}
else {
row.prop("class", null);
row.attr("data-selected", "false");
}
me.refresh_delete_btn();
});
me.refresh_delete_btn();
},
refresh_delete_btn: function() {
$(".delete-items").toggle($(".item-cart .warning").length ? true : false);
},
add_item_thru_barcode: function() {
var me = this;
wn.call({
method: 'accounts.doctype.sales_invoice.pos.get_item_from_barcode',
args: {barcode: this.barcode.$input.val()},
callback: function(r) {
if (r.message) {
me.add_to_cart(r.message[0].name);
me.refresh();
}
else
msgprint(wn._("Invalid Barcode"));
}
});
},
remove_selected_item: function() {
var me = this;
var selected_items = [];
var no_of_items = $("#cart tbody tr").length;
for(var x=0; x<=no_of_items - 1; x++) {
var row = $("#cart tbody tr:eq(" + x + ")");
if(row.attr("data-selected") == "true") {
selected_items.push(row.attr("id"));
}
}
if (!selected_items[0])
msgprint(wn._("Please select any item to remove it"));
var child = wn.model.get_children("Sales Invoice Item", this.frm.doc.name, "entries",
"Sales Invoice");
$.each(child, function(i, d) {
for (var i in selected_items) {
if (d.item_code == selected_items[i]) {
wn.model.clear_doc(d.doctype, d.name);
}
}
});
cur_frm.fields_dict["entries"].grid.refresh();
me.refresh();
},
make_payment: function() {
var me = this;
var no_of_items = $("#cart tbody tr").length;
var mode_of_payment = [];
if (no_of_items == 0)
msgprint(wn._("Payment cannot be made for empty cart"));
else {
wn.call({
method: 'accounts.doctype.sales_invoice.pos.get_mode_of_payment',
callback: function(r) {
for (x=0; x<=r.message.length - 1; x++) {
mode_of_payment.push(r.message[x].name);
}
// show payment wizard
var dialog = new wn.ui.Dialog({
width: 400,
title: 'Payment',
fields: [
{fieldtype:'Data', fieldname:'total_amount', label:'Total Amount', read_only:1},
{fieldtype:'Select', fieldname:'mode_of_payment', label:'Mode of Payment',
options:mode_of_payment.join('\n'), reqd: 1},
{fieldtype:'Button', fieldname:'pay', label:'Pay'}
]
});
dialog.set_values({
"total_amount": $(".grand-total").text()
});
dialog.show();
dialog.get_input("total_amount").attr("disabled", "disabled");
dialog.fields_dict.pay.input.onclick = function() {
cur_frm.set_value("mode_of_payment", dialog.get_values().mode_of_payment);
cur_frm.set_value("paid_amount", dialog.get_values().total_amount);
cur_frm.save();
dialog.hide();
me.refresh();
};
}
});
}
})
}
},
});

View File

@ -0,0 +1,32 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import webnotes
@webnotes.whitelist()
def get_items(price_list, item=None, item_group=None):
condition = ""
if item_group and item_group != "All Item Groups":
condition = "and i.item_group='%s'" % item_group
if item:
condition = "and i.name='%s'" % item
return webnotes.conn.sql("""select
i.name, i.item_name, i.image, ip.ref_rate, ip.ref_currency
from `tabItem` i LEFT JOIN `tabItem Price` ip
ON ip.parent=i.name
and ip.price_list=%s
where
i.is_sales_item='Yes'%s""" % ('%s', condition), (price_list), as_dict=1)
@webnotes.whitelist()
def get_item_from_barcode(barcode):
return webnotes.conn.sql("""select name from `tabItem` where barcode=%s""",
(barcode), as_dict=1)
@webnotes.whitelist()
def get_mode_of_payment():
return webnotes.conn.sql("""select name from `tabMode of Payment`""", as_dict=1)

View File

@ -0,0 +1,15 @@
.pos-item {
height: 200px;
overflow: hidden;
cursor: pointer;
padding-left: 5px !important;
padding-right: 5px !important;
}
.pos-bill {
padding: 20px 5px;
font-family: Monospace;
border: 1px solid #eee;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
}

View File

@ -12,7 +12,7 @@ cur_frm.pformat.print_heading = 'Invoice';
wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js');
wn.require('app/utilities/doctype/sms_control/sms_control.js');
wn.require('app/selling/doctype/sales_common/sales_common.js');
// wn.require('app/accounts/doctype/sales_invoice/pos.js');
wn.require('app/accounts/doctype/sales_invoice/pos.js');
wn.provide("erpnext.accounts");
erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.extend({
@ -25,9 +25,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
this.frm.set_df_property("debit_to", "print_hide", 0);
}
}
// if(this.frm.doc.is_pos && this.frm.doc.docstatus===0) {
// cur_frm.cscript.toggle_pos(true);
// }
cur_frm.cscript.toggle_pos(true);
},
refresh: function(doc, dt, dn) {
@ -58,7 +57,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
cur_frm.add_custom_button('Make Payment Entry', cur_frm.cscript.make_bank_voucher);
}
if (this.frm.doc.docstatus===0) {
if (doc.docstatus===0) {
cur_frm.add_custom_button(wn._('From Sales Order'),
function() {
wn.model.map_current_doc({
@ -92,32 +91,62 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
});
});
if(cint(sys_defaults.fs_pos_view)===1)
cur_frm.cscript.pos_btn();
// cur_frm.add_custom_button(wn._("POS View"), function() {
// cur_frm.cscript.toggle_pos();
// }, 'icon-desktop');
// setTimeout(function() { cur_frm.$pos_btn.click(); }, 1000);
} else {
// hide shown pos for submitted records
if(cur_frm.pos_active) cur_frm.cscript.toggle_pos(false);
}
},
pos_btn: function() {
if(cur_frm.$pos_btn)
cur_frm.$pos_btn.remove();
if(!cur_frm.pos_active) {
var btn_label = wn._("POS View"),
icon = "icon-desktop";
} else {
var btn_label = wn._("Invoice View"),
icon = "icon-file-text";
}
cur_frm.$pos_btn = cur_frm.add_custom_button(btn_label, function() {
cur_frm.cscript.toggle_pos();
cur_frm.cscript.pos_btn();
}, icon);
},
toggle_pos: function(show) {
if((show===true && cur_frm.pos_active) || (show===false && !cur_frm.pos_active)) return;
if(cint(sys_defaults.fs_pos_view)===0) return;
if(!(this.frm.doc.is_pos && this.frm.doc.docstatus===0)) return;
// make pos
if(!cur_frm.pos) {
cur_frm.layout.add_view("pos");
cur_frm.pos = new erpnext.POS(cur_frm.layout.views.pos, cur_frm);
if (!this.frm.doc.selling_price_list)
msgprint(wn._("Please select Price List"))
else {
if((show===true && cur_frm.pos_active) || (show===false && !cur_frm.pos_active)) return;
// make pos
if(!cur_frm.pos) {
cur_frm.layout.add_view("pos");
cur_frm.pos = new erpnext.POS(cur_frm.layout.views.pos, cur_frm);
}
// toggle view
cur_frm.layout.set_view(cur_frm.pos_active ? "" : "pos");
cur_frm.pos_active = !cur_frm.pos_active;
// refresh
if(cur_frm.pos_active)
cur_frm.pos.refresh();
}
// toggle view
cur_frm.layout.set_view(cur_frm.pos_active ? "" : "pos");
cur_frm.pos_active = !cur_frm.pos_active;
// refresh
if(cur_frm.pos_active)
cur_frm.pos.refresh();
},
tc_name: function() {
this.get_terms();
},

View File

@ -1,4 +1,5 @@
{
"app_name": "ERPNext",
"modules": {
"Selling": {
"link": "selling-home",

View File

@ -13,17 +13,27 @@ def execute():
name = question.question[:180]
if webnotes.conn.exists("Note", name):
webnotes.delete_doc("Note", name)
note = webnotes.bean({
similar_questions = webnotes.conn.sql_list("""select name from `tabQuestion`
where question like %s""", "%s%%" % name)
answers = [markdown2.markdown(c) for c in webnotes.conn.sql_list("""
select answer from tabAnswer where question in (%s)""" % \
", ".join(["%s"]*len(similar_questions)), similar_questions)]
webnotes.bean({
"doctype":"Note",
"title": name,
"content": "<hr>".join([markdown2.markdown(c) for c in webnotes.conn.sql_list("""
select answer from tabAnswer where question=%s""", question.name)]),
"content": "<hr>".join(answers),
"owner": question.owner,
"creation": question.creation,
"public": 1
}).insert()
except NameError:
pass
except Exception, e:
if e.args[0] != 1062:
raise e
webnotes.delete_doc("DocType", "Question")
webnotes.delete_doc("DocType", "Answer")

View File

@ -6,9 +6,9 @@ wn.require("app/js/controllers/stock_controller.js");
erpnext.TransactionController = erpnext.stock.StockController.extend({
onload: function() {
var me = this;
if(this.frm.doc.__islocal) {
var me = this,
today = get_today(),
var today = get_today(),
currency = wn.defaults.get_default("currency");
$.each({
@ -30,6 +30,14 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
me.frm.script_manager.trigger("company");
}
if(this.other_fname) {
this[this.other_fname + "_remove"] = this.calculate_taxes_and_totals;
}
if(this.fname) {
this[this.fname + "_remove"] = this.calculate_taxes_and_totals;
}
},
onload_post_render: function() {
@ -311,9 +319,14 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
function(item_code, tax_data) {
if(!item_tax[item_code]) item_tax[item_code] = {};
if($.isArray(tax_data)) {
var tax_rate = tax_data[0] == null ? "" : (flt(tax_data[0], tax_rate_precision) + "%"),
tax_amount = format_currency(flt(tax_data[1], tax_amount_precision), company_currency,
tax_amount_precision);
var tax_rate = "";
if(tax_data[0] != null) {
tax_rate = (tax.charge_type === "Actual") ?
format_currency(flt(tax_data[0], tax_amount_precision), company_currency, tax_amount_precision) :
(flt(tax_data[0], tax_rate_precision) + "%");
}
var tax_amount = format_currency(flt(tax_data[1], tax_amount_precision), company_currency,
tax_amount_precision);
item_tax[item_code][tax.name] = [tax_rate, tax_amount];
} else {

View File

@ -76,8 +76,8 @@ class DocType:
def get_new_item_code(doctype, txt, searchfield, start, page_len, filters):
from controllers.queries import get_match_cond
return webnotes.conn.sql("""select name, description from tabItem
return webnotes.conn.sql("""select name, item_name, description from tabItem
where is_stock_item="No" and is_sales_item="Yes"
and name not in (select name from `tabSales BOM`) and %s like %s
%s limit %s, %s""" % (searchfield, "%s",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-03-07 11:42:58",
"docstatus": 0,
"modified": "2013-08-22 15:21:56",
"modified": "2013-08-22 15:43:07",
"modified_by": "Administrator",
"owner": "Administrator"
},

View File

@ -2,7 +2,7 @@
{
"creation": "2012-12-20 12:50:49",
"docstatus": 0,
"modified": "2013-07-05 14:37:59",
"modified": "2013-08-22 15:36:43",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -184,6 +184,13 @@
"fieldtype": "Check",
"label": "Point of Sale"
},
{
"description": "To enable <b>Point of Sale</b> view",
"doctype": "DocField",
"fieldname": "fs_pos_view",
"fieldtype": "Check",
"label": "POS View"
},
{
"doctype": "DocField",
"fieldname": "production",

View File

@ -72,7 +72,7 @@ def feature_setup():
'fs_exports', 'fs_imports', 'fs_discounts', 'fs_purchase_discounts',
'fs_after_sales_installations', 'fs_projects', 'fs_sales_extras',
'fs_recurring_invoice', 'fs_pos', 'fs_manufacturing', 'fs_quality',
'fs_page_break', 'fs_more_info'
'fs_page_break', 'fs_more_info', 'fs_pos_view'
]
doc.fields.update(dict(zip(flds, [1]*len(flds))))
doc.save()

View File

@ -1,22 +0,0 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
// License: GNU General Public License v3. See license.txt
// render
wn.listview_settings['Purchase Receipt'] = {
add_fields: ["group_concat(`tabPurchase Receipt Item`.prevdoc_docname) \
as purchase_order_no"],
add_columns: [{"content":"purchase_order_no", width:"30%"}],
group_by: "`tabPurchase Receipt`.name",
prepare_data: function(data) {
if(data.purchase_order_no) {
data.purchase_order_no = $.unique(data.purchase_order_no.split(","));
var po_list = [];
$.each(data.purchase_order_no, function(i, v){
if(po_list.indexOf(v)==-1) po_list.push(
repl("<a href=\"#Form/Purchase Order/%(name)s\">%(name)s</a>",
{name: v}));
});
data.purchase_order_no = po_list.join(", ");
}
}
};

View File

@ -248,8 +248,7 @@ def reorder_item():
and exists (select name from `tabItem`
where `tabItem`.name = `tabBin`.item_code and
is_stock_item='Yes' and (is_purchase_item='Yes' or is_sub_contracted_item='Yes') and
(ifnull(end_of_life, '')='') or end_of_life > now())""",
as_dict=True)
(ifnull(end_of_life, '')='' or end_of_life > now()))""", as_dict=True)
for bin in bin_list:
#check if re-order is required
item_reorder = webnotes.conn.get("Item Reorder",
@ -389,4 +388,4 @@ def repost():
"""
from webnotes.model.code import get_obj
for wh in webnotes.conn.sql("select name from tabWarehouse"):
get_obj('Warehouse', wh[0]).repost_stock()
get_obj('Warehouse', wh[0]).repost_stock()

View File

View File

@ -0,0 +1,3 @@
body, #container, .outer {
background-color: #888 !important;
}

View File

@ -0,0 +1,25 @@
<div class="container">
<div class="row" style="margin-top: 100px;">
<div class="col-sm-offset-3 col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
Start ERPNext Demo
</div>
<div class="panel-body">
<p>
<input id="lead-email" type="email"
class="form-control" placeholder="Your Email Id">
</p>
<p>
<button type="submit" id="login_btn"
class="btn btn-primary btn-large">Launch Demo</button>
</p>
<hr>
<p class="text-muted small">Some functionality is disabled for the demo app. The demo data will be cleared regulary. To start your own ERPNext Trial, <a href="https://erpnext.com/pricing-and-signup">click here</a></p>
</div>
</div>
</div>
</div>
<div class="row">
</div>
</div>

View File

@ -0,0 +1,27 @@
$(document).ready(function() {
$(".navbar, footer, .banner, #user-tools").toggle(false);
$("#login_btn").click(function() {
var me = this;
$(this).html("Logging In...").attr("disabled", "disabled");
wn.call({
"method": "login",
args: {
usr: "demo@erpnext.com",
pwd: "demo",
lead_email: $("#lead-email").val(),
},
callback: function(r) {
$(me).attr("disabled", false);
if(r.exc) {
alert("Error, please contact support@erpnext.com");
} else {
console.log("Logged In");
window.location.href = "app.html";
}
}
})
return false;
})
.attr("disabled", false);
})

View File

@ -0,0 +1,13 @@
def on_login(self):
from webnotes.utils import validate_email_add
import conf
if hasattr(conf, "demo_notify_url"):
if webnotes.form_dict.lead_email and validate_email_add(webnotes.form_dict.lead_email):
import requests
response = requests.post(conf.demo_notify_url, data={
"cmd":"website.helpers.contact.send_message",
"subject":"Logged into Demo",
"sender": webnotes.form_dict.lead_email,
"message": "via demo.erpnext.com"
})

View File

Can't render this file because it has a wrong number of fields in line 2.

View File

Before

Width:  |  Height:  |  Size: 221 KiB

After

Width:  |  Height:  |  Size: 221 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -19,18 +19,19 @@ company_abbr = "WP"
country = "United States"
currency = "USD"
time_zone = "America/New York"
start_date = '2010-01-01'
start_date = '2013-01-01'
bank_name = "Citibank"
runs_for = 20
runs_for = None
prob = {
"default": { "make": 0.6, "qty": (1,5) },
"Sales Order": { "make": 0.4, "qty": (1,3) },
"Purchase Order": { "make": 0.7, "qty": (1,15) },
"Purchase Receipt": { "make": 0.7, "qty": (1,15) },
}
def make(reset=False):
webnotes.connect()
webnotes.print_messages = True
#webnotes.print_messages = True
webnotes.mute_emails = True
webnotes.rollback_on_exception = True
@ -49,21 +50,24 @@ def setup():
# make_opening_accounts()
def simulate():
current_date = None
for i in xrange(runs_for):
if not current_date:
# get last stock ledger posting date or use default
last_posting = webnotes.conn.sql("""select max(posting_date) from `tabStock Ledger Entry`""")
if last_posting[0][0]:
current_date = webnotes.utils.add_days(last_posting[0][0], 1)
else:
current_date = webnotes.utils.getdate(start_date)
else:
current_date = webnotes.utils.add_days(current_date, 1)
global runs_for
current_date = webnotes.utils.getdate(start_date)
# continue?
last_posting = webnotes.conn.sql("""select max(posting_date) from `tabStock Ledger Entry`""")
if last_posting[0][0]:
current_date = webnotes.utils.add_days(last_posting[0][0], 1)
# run till today
if not runs_for:
runs_for = webnotes.utils.date_diff(webnotes.utils.nowdate(), current_date)
for i in xrange(runs_for):
print current_date.strftime("%Y-%m-%d")
webnotes.utils.current_date = current_date
if current_date.weekday() in (5, 6):
current_date = webnotes.utils.add_days(current_date, 1)
continue
run_sales(current_date)
@ -71,6 +75,8 @@ def simulate():
run_manufacturing(current_date)
run_stock(current_date)
run_accounts(current_date)
current_date = webnotes.utils.add_days(current_date, 1)
def run_sales(current_date):
if can_make("Quotation"):
@ -135,7 +141,7 @@ def run_stock(current_date):
for po in list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="Total"]))[:how_many("Purchase Receipt")]:
pr = webnotes.bean(make_purchase_receipt(po))
pr.doc.posting_date = current_date
pr.doc.fiscal_year = "2010"
pr.doc.fiscal_year = "2013"
pr.insert()
pr.submit()
webnotes.conn.commit()
@ -149,7 +155,7 @@ def run_stock(current_date):
for so in list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="Total"]))[:how_many("Delivery Note")]:
dn = webnotes.bean(make_delivery_note(so))
dn.doc.posting_date = current_date
dn.doc.fiscal_year = "2010"
dn.doc.fiscal_year = "2013"
dn.insert()
try:
dn.submit()
@ -172,7 +178,7 @@ def run_purchase(current_date):
mr = webnotes.new_bean("Material Request")
mr.doc.material_request_type = "Purchase"
mr.doc.transaction_date = current_date
mr.doc.fiscal_year = "2010"
mr.doc.fiscal_year = "2013"
mr.doclist.append({
"doctype": "Material Request Item",
"parentfield": "indent_details",
@ -191,7 +197,7 @@ def run_purchase(current_date):
if row[0] != "Total":
sq = webnotes.bean(make_supplier_quotation(row[0]))
sq.doc.transaction_date = current_date
sq.doc.fiscal_year = "2010"
sq.doc.fiscal_year = "2013"
sq.insert()
sq.submit()
webnotes.conn.commit()
@ -204,7 +210,7 @@ def run_purchase(current_date):
if row[0] != "Total":
po = webnotes.bean(make_purchase_order(row[0]))
po.doc.transaction_date = current_date
po.doc.fiscal_year = "2010"
po.doc.fiscal_year = "2013"
po.insert()
po.submit()
webnotes.conn.commit()
@ -262,7 +268,7 @@ def make_stock_entry_from_pro(pro_id, purpose, current_date):
st = webnotes.bean(make_stock_entry(pro_id, purpose))
st.doc.posting_date = current_date
st.doc.fiscal_year = "2010"
st.doc.fiscal_year = "2013"
st.doc.expense_adjustment_account = "Stock in Hand - WP"
try:
st.insert()
@ -281,7 +287,7 @@ def make_quotation(current_date):
"customer": get_random("Customer"),
"order_type": "Sales",
"transaction_date": current_date,
"fiscal_year": "2010"
"fiscal_year": "2013"
}])
add_random_children(b, {
@ -348,8 +354,9 @@ def how_many(doctype):
def install():
print "Creating Fresh Database..."
from webnotes.install_lib.install import Installer
import conf
inst = Installer('root')
inst.import_from_db("demo", verbose = 1)
inst.import_from_db(conf.demo_db_name, verbose = 1)
def complete_setup():
print "Complete Setup..."
@ -391,6 +398,7 @@ def make_bank_account():
}).insert()
webnotes.set_value("Company", company, "default_bank_account", ba.doc.name)
webnotes.conn.commit()
def import_data(dt, submit=False):
if not isinstance(dt, (tuple, list)):

View File

@ -0,0 +1,81 @@
if __name__=="__main__":
import sys
sys.path.extend([".", "lib", "app"])
import webnotes, os
def make_demo_app():
import utilities.demo.make_demo
utilities.demo.make_demo.make(reset=True)
def make_demo_user():
if webnotes.conn.exists("Profile", "demo@erpnext.com"):
webnotes.delete_doc("Profile", "demo@erpnext.com")
p = webnotes.new_bean("Profile")
p.doc.email = "demo@erpnext.com"
p.doc.first_name = "Demo"
p.doc.last_name = "User"
p.doc.enabled = 1
p.doc.user_type = "ERPNext Demo"
p.doc.send_invite_email = 0
p.doc.new_password = "demo"
p.insert()
for role in ("Accounts Manager", "Analytics", "Expense Approver", "Accounts User",
"Leave Approver", "Blogger", "Customer", "Sales Manager", "Employee", "Support Manager",
"HR Manager", "HR User", "Maintenance Manager", "Maintenance User", "Material Manager",
"Material Master Manager", "Material User", "Partner", "Manufacturing Manager",
"Manufacturing User", "Projects User", "Purchase Manager", "Purchase Master Manager",
"Purchase User", "Quality Manager", "Report Manager", "Sales Master Manager", "Sales User",
"Supplier", "Support Team"):
p.doclist.append({
"doctype": "UserRole",
"parentfield": "user_roles",
"role": role
})
p.save()
webnotes.conn.commit()
def make_demo_login_page():
webnotes.conn.set_value("Website Settings", None, "home_page", "")
webnotes.conn.sql("""delete from `tabWeb Page` where name='demo-login'""")
p = webnotes.new_bean("Web Page")
p.doc.title = "Demo Login"
p.doc.published = 1
p.doc.description = "ERPNext Demo Login"
with open(os.path.join(os.path.dirname(__file__), "demo-login.html"), "r") as dfile:
p.doc.main_section = dfile.read()
p.doc.insert_code = 1
with open(os.path.join(os.path.dirname(__file__), "demo-login.js"), "r") as dfile:
p.doc.javascript = dfile.read()
p.doc.insert_style = 1
with open(os.path.join(os.path.dirname(__file__), "demo-login.css"), "r") as dfile:
p.doc.css = dfile.read()
p.insert()
webnotes.conn.set_value("Website Settings", None, "home_page", "demo-login")
webnotes.conn.commit()
def make_demo_on_login_script():
webnotes.conn.sql("""delete from `tabCustom Script` where dt='Control Panel'""")
s = webnotes.new_bean("Custom Script")
s.doc.dt = "Control Panel"
s.doc.script_type = "Server"
with open(os.path.join(os.path.dirname(__file__), "demo_control_panel.py"), "r") as dfile:
s.doc.script = dfile.read()
if __name__=="__main__":
webnotes.connect()
webnotes.mute_emails = 1
make_demo_app()
make_demo_user()
make_demo_login_page()
make_demo_on_login_script()

View File

@ -4,6 +4,14 @@
// update parent select
$.extend(cur_frm.cscript, {
refresh: function(doc) {
cur_frm.add_custom_button("Auto Build Website", function() {
cur_frm.call({
doc: cur_frm.doc,
method: "make_website"
})
}, 'icon-magic')
},
onload_post_render: function(doc) {
this.set_parent_label_options();
},

View File

@ -13,6 +13,26 @@ class DocType:
self.set_home_page()
self.validate_top_bar_items()
self.validate_footer_items()
def make_website(self):
# set item pages
for name in webnotes.conn.sql_list("""select name from tabItem where
ifnull(show_in_website, 0)=0 and is_sales_item ='Yes' """):
webnotes.msgprint("Setting 'Show in Website' for:" + name)
item = webnotes.bean("Item", name)
item.doc.show_in_website = 1
item.doc.website_warehouse = item.doc.default_warehouse
item.doc.website_image = item.doc.image
item.save()
# set item group pages
for name in webnotes.conn.sql_list("""select name from `tabItem Group` where
ifnull(show_in_website, 0)=0 and exists (select name from tabItem where
ifnull(show_in_website, 0)=1)"""):
webnotes.msgprint("Setting 'Show in Website' for:" + name)
item_group = webnotes.bean("Item Group", name)
item_group.doc.show_in_website = 1
item_group.save()
def validate_top_bar_items(self):
"""validate url in top bar items"""