[fix] [minor] fixed conflict while merging with master

This commit is contained in:
Nabin Hait 2013-08-19 11:06:06 +05:30
commit 44da6f2efe
206 changed files with 5830 additions and 1272 deletions

View File

@ -1,21 +1,22 @@
[
{
"owner": "Administrator",
"docstatus": 0,
"creation": "2011-12-21 11:08:55",
"docstatus": 0,
"modified": "2013-08-16 16:15:46",
"modified_by": "Administrator",
"modified": "2012-03-20 12:29:49"
"owner": "Administrator"
},
{
"doc_type": "Sales Invoice",
"name": "__common__",
"module": "Accounts",
"doctype": "Print Format",
"html": "<html>\n<head>\n<!--Other charges function-->\n<script>\nvar make_row = function(title,val,bold){\nvar bstart = '<b>'; var bend = '</b>';\nreturn '<tr><td style=\"width:50%\">'+(bold?bstart:'')+title+(bold?bend:'')+'</td>'\n +'<td style=\"width:20%\">'+doc.currency+'</td>'\n +'<td style=\"width:30%;text-align:right\">'+(val?val:'0.00')+'</td>'\n +'</tr>'\n}\nvar make_row1 = function(title,val,bold){\n var bstart = '<b>'; var bend = '</b>';\n \n return '<tr style=\"font-family:courier new; line-height:150%\"><td style=\"width:50%\">'+(bold?bstart:'')+title+(bold?bend:'')+'</td>'\n +'<td style=\"width:50%;text-align:right\">'+(bold?bstart:'')+(val?val:'0.00')+(bold?bend:'')+'</td>'\n +'</tr>'\n}\n\nfunction get_letter_head() {\n // add letter head\n var cp = wn.boot.control_panel;\n if(doc.letter_head)\n var lh= cstr(_p.letter_heads[doc.letter_head]);\n else if(cp.letter_head)\n var lh= cp.letter_head;\n else \n var lh= '';\n \n return lh;\n}\n\nfunction get_tax_details(){\n var cl = getchildren('Sales Taxes and Charges',doc.name,'other_charges');\n var out = '';\n\n out += '<div><table style=\"float: right;\">';\n for(var i=0;i<cl.length;i++){\n if(cl[i].tax_amount) {\n out += make_row1(cl[i].description,fmt_money(convert_rate(cl[i].tax_amount)),0);\n }\n }\n out += make_row1('TOTAL',doc.currency + \" \" + fmt_money(convert_rate(doc.grand_total)),1);\n out +='</table></div>';\n return out;\n}\n\nfunction convert_rate(val){ \n var new_val = flt(val)/flt(doc.conversion_rate);\n return new_val;\n}\n</script>\n<style>\n table, td, tr, div, span {\n font-family: courier new;\n line-height: 200%;\n }\n</style>\n</head>\n\n<body>\n<table width=\"100%\" style=\"font-family: courier new; line-height:200%\">\n<tr>\n <td align=\"left\">NO: <script>doc.name</script></td>\n <td align=\"right\">DATE: <script>date.str_to_user(doc.posting_date)</script></td>\n</tr>\n<tr>\n <td>M/s <script>doc.contact_display</script></td>\n</tr>\n</table>\n<!--Item Table-->\n<div>\n<script>\nvar t = print_table('Sales Invoice', doc.name, 'entries', 'Sales Invoice Item',\n ['description','qty','export_rate','export_amount'], ['ITEM', 'QTY','RATE','AMOUNT'],\n ['35%','20%','20%','25%']);\nif(t.appendChild) { // single\n out = t.innerHTML.replace(/style=\"/gi,'style=\"font-family:courier new;line-height:150%;');\n} else { //multiple\n out = '<table class=\"None\" border=\"0px\" width=\"100%\" style=\"border:0px; font-family:courier-new\">';\n\n for(var i=0;i<t.length;i++) {\n if(i==0) {\n out += '<tr>' + t[i].childNodes[0].childNodes[0].childNodes[0].innerHTML\n .replace(/style=\"border: 1px solid rgb\\(0, 0, 0\\);/gi,'style=\"font-family:courier new;')\n + '</tr>';\n }\n out += '<tr>' + t[i].childNodes[0].childNodes[0].childNodes[1].innerHTML\n .replace(/style=\"border: 1px solid rgb\\(0, 0, 0\\);/gi,'style=\"font-family:courier new;')\n + '</tr>';\n }\n out += '</table>';\n}\nout;\n</script>\n</div>\n<!--Tax table-->\n<div><script>get_tax_details();</script></div><br />\n<table style=\"font-family:courier new;\">\n <tr><td><b><script>doc.terms</script></b></td></tr>\n <tr><td nowrap><b>For <script>doc.company</script></b></td></tr>\n <tr><td>&nbsp;</td></tr>\n <tr><td nowrap><b>Signatory</b></td></tr>\n</table>\n</body>\n</html>\n",
"html": "<html>\n<head>\n<!--Other charges function-->\n<script>\nvar make_row = function(title,val,bold){\nvar bstart = '<b>'; var bend = '</b>';\nreturn '<tr><td style=\"width:50%\">'+(bold?bstart:'')+title+(bold?bend:'')+'</td>'\n +'<td style=\"width:20%\">'+doc.currency+'</td>'\n +'<td style=\"width:30%;text-align:right\">'+(val?val:'0.00')+'</td>'\n +'</tr>'\n}\nvar make_row1 = function(title,val,bold){\n var bstart = '<b>'; var bend = '</b>';\n \n return '<tr style=\"font-family:courier new; line-height:150%\"><td style=\"width:50%\">'+(bold?bstart:'')+title+(bold?bend:'')+'</td>'\n +'<td style=\"width:50%;text-align:right\">'+(bold?bstart:'')+(val?val:'0.00')+(bold?bend:'')+'</td>'\n +'</tr>'\n}\n\nfunction get_letter_head() {\n // add letter head\n var cp = wn.boot.control_panel;\n if(doc.letter_head)\n var lh= cstr(_p.letter_heads[doc.letter_head]);\n else if(cp.letter_head)\n var lh= cp.letter_head;\n else \n var lh= '';\n \n return lh;\n}\n\nfunction get_tax_details(){\n var cl = getchildren('Sales Taxes and Charges',doc.name,'other_charges');\n var out = '';\n\n out += '<div><table style=\"float: right;\">';\n for(var i=0;i<cl.length;i++){\n if(cl[i].tax_amount) {\n out += make_row1(cl[i].description,fmt_money(convert_rate(cl[i].tax_amount)),0);\n }\n }\n out += make_row1('TOTAL',doc.currency + \" \" + fmt_money(convert_rate(doc.grand_total)),1);\n out +='</table></div>';\n return out;\n}\n\nfunction convert_rate(val){ \n var new_val = flt(val)/flt(doc.conversion_rate);\n return new_val;\n}\n</script>\n<style>\n table, td, tr, div, span {\n font-family: courier new;\n line-height: 200%;\n }\n</style>\n</head>\n\n<body>\n<table width=\"100%\" style=\"font-family: courier new; line-height:200%\">\n<tr>\n <td align=\"left\">NO: <script>doc.name</script></td>\n <td align=\"right\">DATE: <script>date.str_to_user(doc.posting_date)</script></td>\n</tr>\n<tr>\n <td>M/s <script>doc.contact_display</script></td>\n</tr>\n</table>\n<!--Item Table-->\n<div>\n<script>\nvar t = print_table(\n \t\t\t'Sales Invoice',\n\t\t\t\tdoc.name,\n\t\t\t\t'entries',\n\t\t\t\t'Sales Invoice Item',\n\t\t\t\t[// Here specify the table columns to be displayed\n\t\t\t\t\t'SR', 'description', 'qty', 'export_rate', 'export_amount'\n\t\t\t\t],\n\t\t\t\t[// Here specify the labels of column headings\n\t\t\t\t\t'Sr', 'Description', 'Qty', 'Rate', 'Amount'\n\t\t\t\t],\n\t\t\t\t[// Here specify the column widths\n\t\t\t\t\t'5%', '35%', '20%', '20%', '20%'\n\t\t\t\t],\n\t\t\t\tnull,\n\t\t\t\tnull\n\t\t\t);\nif(t.appendChild) { // single\n out = t.innerHTML.replace(/style=\"/gi,'style=\"font-family:courier new;line-height:150%;');\n} else { //multiple\n out = '<table class=\"None\" border=\"0px\" width=\"100%\" style=\"border:0px; font-family:courier-new\">';\n\n for(var i=0;i<t.length;i++) {\n if(i==0) {\n out += '<tr>' + t[i].childNodes[0].childNodes[0].childNodes[0].innerHTML\n .replace(/style=\"border: 1px solid rgb\\(0, 0, 0\\);/gi,'style=\"font-family:courier new;')\n + '</tr>';\n }\n out += '<tr>' + t[i].childNodes[0].childNodes[0].childNodes[1].innerHTML\n .replace(/style=\"border: 1px solid rgb\\(0, 0, 0\\);/gi,'style=\"font-family:courier new;')\n + '</tr>';\n }\n out += '</table>';\n}\nout;\n</script>\n</div>\n<!--Tax table-->\n<div><script>get_tax_details();</script></div><br />\n<table style=\"font-family:courier new;\">\n <tr><td><b><script>doc.terms</script></b></td></tr>\n <tr><td nowrap><b>For <script>doc.company</script></b></td></tr>\n <tr><td>&nbsp;</td></tr>\n <tr><td nowrap><b>Signatory</b></td></tr>\n</table>\n</body>\n</html>\n",
"module": "Accounts",
"name": "__common__",
"print_format_type": "Client",
"standard": "Yes"
},
{
"name": "POS Invoice",
"doctype": "Print Format"
"doctype": "Print Format",
"name": "POS Invoice"
}
]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
{
"creation": "2013-03-07 11:55:06",
"docstatus": 0,
"modified": "2013-07-05 14:29:48",
"modified": "2013-08-08 14:21:55",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -50,7 +50,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"label": "Document Numbering Series",
"options": "\nC-FORM/",
"read_only": 0,
"reqd": 1

View File

@ -2,7 +2,7 @@
{
"creation": "2013-03-25 10:53:52",
"docstatus": 0,
"modified": "2013-07-05 14:43:51",
"modified": "2013-08-08 14:21:56",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -58,7 +58,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"label": "Document Numbering Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:07",
"docstatus": 0,
"modified": "2013-07-22 15:31:33",
"modified": "2013-08-12 17:13:23",
"modified_by": "Administrator",
"owner": "jai@webnotestech.com"
},
@ -35,7 +35,6 @@
"permlevel": 0,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"submit": 1,
"write": 1
},
@ -104,6 +103,7 @@
"oldfieldtype": "Column Break"
},
{
"description": "The account head under Liability, in which Profit/Loss will be booked",
"doctype": "DocField",
"fieldname": "closing_account_head",
"fieldtype": "Link",
@ -131,6 +131,11 @@
"reqd": 1
},
{
"doctype": "DocPerm"
"doctype": "DocPerm",
"role": "System Manager"
},
{
"doctype": "DocPerm",
"role": "Accounts Manager"
}
]

View File

@ -6,7 +6,7 @@ cur_frm.cscript.onload = function(doc,cdt,cdn){
if(r.message) set_field_options('naming_series', r.message);
});
cur_frm.set_query("price_list_name", function() {
cur_frm.set_query("selling_price_list", function() {
return { filters: { buying_or_selling: "Selling" } };
});
}

View File

@ -2,7 +2,7 @@
{
"creation": "2013-05-24 12:15:51",
"docstatus": 0,
"modified": "2013-08-05 16:51:22",
"modified": "2013-08-09 16:35:03",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -62,7 +62,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"label": "Document Numbering Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
@ -92,7 +92,7 @@
},
{
"doctype": "DocField",
"fieldname": "price_list_name",
"fieldname": "selling_price_list",
"fieldtype": "Link",
"label": "Price List",
"oldfieldname": "price_list_name",
@ -131,12 +131,12 @@
},
{
"doctype": "DocField",
"fieldname": "customer_account",
"fieldname": "customer",
"fieldtype": "Link",
"label": "Customer Account",
"label": "Customer",
"oldfieldname": "customer_account",
"oldfieldtype": "Link",
"options": "Account",
"options": "Customer",
"read_only": 0,
"reqd": 0
},

View File

@ -7,7 +7,7 @@ test_records = [
"name": "_Test POS Setting",
"currency": "INR",
"conversion_rate": 1.0,
"price_list_name": "_Test Price List",
"selling_price_list": "_Test Price List",
"company": "_Test Company",
"warehouse": "_Test Warehouse - _TC",
"territory": "_Test Territory",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-05-21 16:16:39",
"docstatus": 0,
"modified": "2013-08-01 16:49:49",
"modified": "2013-08-09 14:45:35",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -59,7 +59,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"label": "Document Numbering Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
@ -242,7 +242,7 @@
{
"description": "Consider this Price List for fetching rate. (only which have \"For Buying\" as checked)",
"doctype": "DocField",
"fieldname": "price_list_name",
"fieldname": "buying_price_list",
"fieldtype": "Link",
"label": "Price List",
"options": "Price List",
@ -250,7 +250,7 @@
"read_only": 0
},
{
"depends_on": "price_list_name",
"depends_on": "buying_price_list",
"doctype": "DocField",
"fieldname": "price_list_currency",
"fieldtype": "Link",
@ -260,7 +260,7 @@
"read_only": 1
},
{
"depends_on": "price_list_name",
"depends_on": "buying_price_list",
"doctype": "DocField",
"fieldname": "plc_conversion_rate",
"fieldtype": "Float",

View File

@ -98,8 +98,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
// }, 'icon-desktop');
}
cur_frm.cscript.hide_fields(doc, dt, dn);
},
toggle_pos: function(show) {
@ -178,6 +176,11 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
entries_add: function(doc, cdt, cdn) {
var row = wn.model.get_doc(cdt, cdn);
this.frm.script_manager.copy_from_first_row("entries", row, ["income_account", "cost_center"]);
},
set_dynamic_labels: function() {
this._super();
this.hide_fields(this.frm.doc);
}
});
@ -201,7 +204,10 @@ cur_frm.cscript.hide_fields = function(doc) {
cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_normal, false);
} else {
hide_field('payments_section');
unhide_field(par_flds);
for (i in par_flds) {
var docfield = wn.meta.docfield_map[doc.doctype][par_flds[i]];
if(!docfield.hidden) unhide_field(par_flds[i]);
}
cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_normal, true);
}

View File

@ -162,12 +162,22 @@ class DocType(SellingController):
def set_missing_values(self, for_validate=False):
self.set_pos_fields(for_validate)
if not self.doc.debit_to:
self.doc.debit_to = self.get_customer_account()
if not self.doc.due_date:
self.doc.due_date = self.get_due_date()
super(DocType, self).set_missing_values(for_validate)
def set_customer_defaults(self):
# TODO cleanup these methods
self.doc.fields.update(self.get_debit_to())
self.get_cust_and_due_date()
if self.doc.customer:
self.doc.debit_to = self.get_customer_account()
elif self.doc.debit_to:
self.doc.customer = webnotes.conn.get_value('Account', self.doc.debit_to, 'master_name')
self.doc.due_date = self.get_due_date()
super(DocType, self).set_customer_defaults()
@ -197,20 +207,12 @@ class DocType(SellingController):
if pos:
self.doc.conversion_rate = flt(pos.conversion_rate)
if not self.doc.debit_to:
self.doc.debit_to = self.doc.customer and webnotes.conn.get_value("Account", {
"name": self.doc.customer + " - " + self.get_company_abbr(),
"docstatus": ["!=", 2]
}) or pos.customer_account
if self.doc.debit_to and not self.doc.customer:
self.doc.customer = webnotes.conn.get_value("Account", {
"name": self.doc.debit_to,
"master_type": "Customer"
}, "master_name")
if not for_validate:
self.doc.customer = pos.customer
self.set_customer_defaults()
for fieldname in ('territory', 'naming_series', 'currency', 'charge', 'letter_head', 'tc_name',
'price_list_name', 'company', 'select_print_heading', 'cash_bank_account'):
'selling_price_list', 'company', 'select_print_heading', 'cash_bank_account'):
if (not for_validate) or (for_validate and not self.doc.fields.get(fieldname)):
self.doc.fields[fieldname] = pos.get(fieldname)
@ -251,27 +253,24 @@ class DocType(SellingController):
You must first create it from the Customer Master" %
(self.doc.customer, self.doc.company))
def get_debit_to(self):
acc_head = self.get_customer_account()
return acc_head and {'debit_to' : acc_head} or {}
def get_cust_and_due_date(self):
def get_due_date(self):
"""Set Due Date = Posting Date + Credit Days"""
due_date = None
if self.doc.posting_date:
credit_days = 0
if self.doc.debit_to:
credit_days = webnotes.conn.get_value("Account", self.doc.debit_to, "credit_days")
if self.doc.customer and not credit_days:
credit_days = webnotes.conn.get_value("Customer", self.doc.customer, "credit_days")
if self.doc.company and not credit_days:
credit_days = webnotes.conn.get_value("Company", self.doc.company, "credit_days")
if credit_days:
self.doc.due_date = add_days(self.doc.posting_date, credit_days)
due_date = add_days(self.doc.posting_date, credit_days)
else:
self.doc.due_date = self.doc.posting_date
if self.doc.debit_to:
self.doc.customer = webnotes.conn.get_value('Account',self.doc.debit_to,'master_name')
due_date = self.doc.posting_date
return due_date
def get_barcode_details(self, barcode):
return get_obj('Sales Common').get_barcode_details(barcode)
@ -510,18 +509,20 @@ class DocType(SellingController):
if not d.warehouse:
d.warehouse = cstr(w)
if flt(self.doc.paid_amount) == 0:
if self.doc.cash_bank_account:
webnotes.conn.set(self.doc, 'paid_amount',
(flt(self.doc.grand_total) - flt(self.doc.write_off_amount)))
else:
# show message that the amount is not paid
webnotes.conn.set(self.doc,'paid_amount',0)
webnotes.msgprint("Note: Payment Entry will not be created since 'Cash/Bank Account' was not specified.")
self.make_packing_list()
else:
self.doclist = self.doc.clear_table(self.doclist, 'packing_details')
if cint(self.doc.is_pos) == 1:
if flt(self.doc.paid_amount) == 0:
if self.doc.cash_bank_account:
webnotes.conn.set(self.doc, 'paid_amount',
(flt(self.doc.grand_total) - flt(self.doc.write_off_amount)))
else:
# show message that the amount is not paid
webnotes.conn.set(self.doc,'paid_amount',0)
webnotes.msgprint("Note: Payment Entry will not be created since 'Cash/Bank Account' was not specified.")
else:
webnotes.conn.set(self.doc,'paid_amount',0)
def check_prev_docstatus(self):

View File

@ -2,7 +2,7 @@
{
"creation": "2013-05-24 19:29:05",
"docstatus": 0,
"modified": "2013-07-26 11:16:58",
"modified": "2013-08-09 14:45:42",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -52,7 +52,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"label": "Document Numbering Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
@ -246,7 +246,7 @@
},
{
"doctype": "DocField",
"fieldname": "price_list_name",
"fieldname": "selling_price_list",
"fieldtype": "Link",
"label": "Price List",
"oldfieldname": "price_list_name",

View File

@ -675,7 +675,7 @@ test_records = [
"plc_conversion_rate": 1.0,
"posting_date": "2013-01-23",
"price_list_currency": "INR",
"price_list_name": "_Test Price List",
"selling_price_list": "_Test Price List",
"territory": "_Test Territory"
},
{
@ -738,7 +738,7 @@ test_records = [
"plc_conversion_rate": 1.0,
"posting_date": "2013-03-07",
"price_list_currency": "INR",
"price_list_name": "_Test Price List",
"selling_price_list": "_Test Price List",
"territory": "_Test Territory"
},
{
@ -789,7 +789,7 @@ test_records = [
"plc_conversion_rate": 1.0,
"posting_date": "2013-01-23",
"price_list_currency": "INR",
"price_list_name": "_Test Price List",
"selling_price_list": "_Test Price List",
"territory": "_Test Territory",
},
# items
@ -914,7 +914,7 @@ test_records = [
"plc_conversion_rate": 1.0,
"posting_date": "2013-01-23",
"price_list_currency": "INR",
"price_list_name": "_Test Price List",
"selling_price_list": "_Test Price List",
"territory": "_Test Territory",
},
# items
@ -925,7 +925,6 @@ test_records = [
"item_name": "_Test Item Home Desktop 100",
"qty": 10,
"ref_rate": 62.5,
"export_rate": 62.5,
"stock_uom": "_Test UOM",
"item_tax_rate": json.dumps({"_Test Account Excise Duty - _TC": 10}),
"income_account": "Sales - _TC",
@ -939,7 +938,6 @@ test_records = [
"item_name": "_Test Item Home Desktop 200",
"qty": 5,
"ref_rate": 190.66,
"export_rate": 190.66,
"stock_uom": "_Test UOM",
"income_account": "Sales - _TC",
"cost_center": "_Test Cost Center - _TC",

View File

@ -170,7 +170,12 @@ erpnext.AccountsChart = Class.extend({
show_ledger: function() {
var me = this;
var node = me.selected_node();
wn.set_route("general-ledger", "account=" + node.data('label'));
wn.route_options = {
"account": node.data('label'),
"from_date": sys_defaults.year_start_date,
"to_date": sys_defaults.year_end_date
};
wn.set_route("general-ledger");
},
rename: function() {
var node = this.selected_node();

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-27 16:30:52",
"docstatus": 0,
"modified": "2013-07-11 14:41:59",
"modified": "2013-08-14 12:47:45",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -19,14 +19,18 @@
"name": "__common__",
"parent": "Financial Statements",
"parentfield": "roles",
"parenttype": "Page",
"role": "Accounts Manager"
"parenttype": "Page"
},
{
"doctype": "Page",
"name": "Financial Statements"
},
{
"doctype": "Page Role"
"doctype": "Page Role",
"role": "Accounts Manager"
},
{
"doctype": "Page Role",
"role": "Analytics"
}
]

View File

@ -389,7 +389,8 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({
grid: { hoverable: true, clickable: true },
xaxis: { mode: "time",
min: dateutil.str_to_obj(this.from_date).getTime(),
max: dateutil.str_to_obj(this.to_date).getTime() }
max: dateutil.str_to_obj(this.to_date).getTime() },
series: { downsample: { threshold: 1000 } }
}
},
});

View File

@ -47,18 +47,20 @@ def get_columns(filters):
msgprint(_("Please specify") + ": " + label,
raise_exception=True)
columns = ["Cost Center:Link/Cost Center:100", "Account:Link/Account:100"]
columns = ["Cost Center:Link/Cost Center:120", "Account:Link/Account:120"]
group_months = False if filters["period"] == "Monthly" else True
for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]):
for label in ["Target (%s)", "Actual (%s)", "Variance (%s)"]:
if group_months:
columns.append(label % (from_date.strftime("%b") + " - " + to_date.strftime("%b")))
label = label % (from_date.strftime("%b") + " - " + to_date.strftime("%b"))
else:
columns.append(label % from_date.strftime("%b"))
label = label % from_date.strftime("%b")
columns.append(label+":Float:120")
return columns + ["Total Target::80", "Total Actual::80", "Total Variance::80"]
return columns + ["Total Target::120", "Total Actual::120", "Total Variance::120"]
#Get cost center & target details
def get_costcenter_target_details(filters):
@ -66,19 +68,17 @@ def get_costcenter_target_details(filters):
cc.parent_cost_center, bd.account, bd.budget_allocated
from `tabCost Center` cc, `tabBudget Detail` bd
where bd.parent=cc.name and bd.fiscal_year=%s and
cc.company=%s and ifnull(cc.distribution_id, '')!=''
order by cc.name""" % ('%s', '%s'),
cc.company=%s order by cc.name""" % ('%s', '%s'),
(filters.get("fiscal_year"), filters.get("company")), as_dict=1)
#Get target distribution details of accounts of cost center
def get_target_distribution_details(filters):
target_details = {}
for d in webnotes.conn.sql("""select bdd.month, bdd.percentage_allocation \
from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd, \
`tabCost Center` cc where bdd.parent=bd.name and cc.distribution_id=bd.name and \
bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
target_details.setdefault(d.month, d)
for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation \
from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd
where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
target_details.setdefault(d.name, {}).setdefault(d.month, d.percentage_allocation)
return target_details
@ -99,15 +99,19 @@ def get_costcenter_account_month_map(filters):
cam_map = {}
for ccd in costcenter_target_details:
for month in tdd:
for month_id in range(1, 13):
month = datetime.date(2013, month_id, 1).strftime('%B')
cam_map.setdefault(ccd.name, {}).setdefault(ccd.account, {})\
.setdefault(month, webnotes._dict({
"target": 0.0, "actual": 0.0
}))
.setdefault(month, webnotes._dict({
"target": 0.0, "actual": 0.0
}))
tav_dict = cam_map[ccd.name][ccd.account][month]
tav_dict.target = flt(ccd.budget_allocated) * \
(tdd[month]["percentage_allocation"]/100)
month_percentage = ccd.distribution_id and \
tdd.get(ccd.distribution_id, {}).get(month, 0) or 100.0/12
tav_dict.target = flt(flt(ccd.budget_allocated) * month_percentage /100)
for ad in actual_details:
if ad.month_name == month and ad.account == ccd.account \

View File

@ -10,9 +10,7 @@ def execute(filters=None):
if not filters: filters = {}
stock_ledger_entries = get_stock_ledger_entries(filters)
source = get_source_data(filters)
item_sales_bom = get_item_sales_bom()
columns = ["Delivery Note/Sales Invoice::120", "Link::30", "Posting Date:Date", "Posting Time",
@ -20,12 +18,12 @@ def execute(filters=None):
"Qty:Float", "Selling Rate:Currency", "Avg. Buying Rate:Currency",
"Selling Amount:Currency", "Buying Amount:Currency",
"Gross Profit:Currency", "Gross Profit %:Percent", "Project:Link/Project"]
data = []
for row in source:
selling_amount = flt(row.amount)
buying_amount = get_buying_amount(row.item_code, row.warehouse, -1*row.qty,
row.parenttype, row.name, row.item_row, stock_ledger_entries,
buying_amount = get_buying_amount(row.item_code, row.parenttype, row.name, row.item_row,
stock_ledger_entries.get((row.item_code, row.warehouse), []),
item_sales_bom.get(row.parenttype, {}).get(row.name, webnotes._dict()))
buying_amount = buying_amount > 0 and buying_amount or 0
@ -56,8 +54,17 @@ def get_stock_ledger_entries(filters):
query += """ and company=%(company)s"""
query += " order by item_code desc, warehouse desc, posting_date desc, posting_time desc, name desc"
res = webnotes.conn.sql(query, filters, as_dict=True)
out = {}
for r in res:
if (r.item_code, r.warehouse) not in out:
out[(r.item_code, r.warehouse)] = []
out[(r.item_code, r.warehouse)].append(r)
return webnotes.conn.sql(query, filters, as_dict=True)
return out
def get_item_sales_bom():
item_sales_bom = {}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -11,6 +11,6 @@ class DocType:
self.doc, self.doclist = d, dl
def validate(self):
for key in ["supplier_type", "supp_master_name", "maintain_same_rate"]:
for key in ["supplier_type", "supp_master_name", "maintain_same_rate", "buying_price_list"]:
webnotes.conn.set_default(key, self.doc.fields.get(key, ""))

View File

@ -2,7 +2,7 @@
{
"creation": "2013-06-25 11:04:03",
"docstatus": 0,
"modified": "2013-07-05 14:29:41",
"modified": "2013-08-09 14:38:46",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -53,6 +53,13 @@
"label": "Default Supplier Type",
"options": "Supplier Type"
},
{
"doctype": "DocField",
"fieldname": "buying_price_list",
"fieldtype": "Link",
"label": "Default Buying Price List",
"options": "Price List"
},
{
"doctype": "DocField",
"fieldname": "column_break_3",

View File

@ -18,8 +18,8 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
setup_queries: function() {
var me = this;
if(this.frm.fields_dict.price_list_name) {
this.frm.set_query("price_list_name", function() {
if(this.frm.fields_dict.buying_price_list) {
this.frm.set_query("buying_price_list", function() {
return{
filters: { 'buying_or_selling': "Buying" }
}
@ -29,7 +29,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
return{
query: "controllers.queries.get_price_list_currency",
filters: {
'price_list_name': me.frm.doc.price_list_name,
'price_list': me.frm.doc.buying_price_list,
'buying_or_selling': "Buying"
}
}
@ -77,7 +77,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
msgprint(wn._("Please specify Company"));
} else {
var me = this;
var price_list_name = this.frm.doc.price_list_name;
var buying_price_list = this.frm.doc.buying_price_list;
return this.frm.call({
doc: this.frm.doc,
@ -85,7 +85,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
freeze: true,
callback: function(r) {
if(!r.exc) {
if(me.frm.doc.price_list_name !== price_list_name) me.price_list_name();
if(me.frm.doc.buying_price_list !== buying_price_list) me.buying_price_list();
}
}
});
@ -132,7 +132,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
docname: me.frm.doc.name,
supplier: me.frm.doc.supplier,
conversion_rate: me.frm.doc.conversion_rate,
price_list_name: me.frm.doc.price_list_name,
buying_price_list: me.frm.doc.buying_price_list,
price_list_currency: me.frm.doc.price_list_currency,
plc_conversion_rate: me.frm.doc.plc_conversion_rate,
is_subcontracted: me.frm.doc.is_subcontracted,
@ -151,8 +151,8 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
}
},
price_list_name: function() {
this._super("buying");
buying_price_list: function() {
this.get_price_list_currency("buying");
},
import_ref_rate: function(doc, cdt, cdn) {

View File

@ -196,7 +196,6 @@ def make_purchase_receipt(source_name, target_doclist=None):
bean.run_method("set_missing_values")
def update_item(obj, target, source_parent):
target.conversion_factor = 1
target.qty = flt(obj.qty) - flt(obj.received_qty)
target.stock_qty = (flt(obj.qty) - flt(obj.received_qty)) * flt(obj.conversion_factor)
target.import_amount = (flt(obj.qty) - flt(obj.received_qty)) * flt(obj.import_rate)
@ -237,7 +236,6 @@ def make_purchase_invoice(source_name, target_doclist=None):
bean.run_method("set_supplier_defaults")
def update_item(obj, target, source_parent):
target.conversion_factor = 1
target.import_amount = flt(obj.import_amount) - flt(obj.billed_amt)
target.amount = target.import_amount * flt(source_parent.conversion_rate)
if flt(obj.purchase_rate):

View File

@ -2,7 +2,7 @@
{
"creation": "2013-05-21 16:16:39",
"docstatus": 0,
"modified": "2013-08-01 16:49:16",
"modified": "2013-08-09 14:45:51",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -52,7 +52,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"label": "Document Numbering Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
@ -211,14 +211,14 @@
{
"description": "Consider this Price List for fetching rate. (only which have \"For Buying\" as checked)",
"doctype": "DocField",
"fieldname": "price_list_name",
"fieldname": "buying_price_list",
"fieldtype": "Link",
"label": "Price List",
"options": "Price List",
"print_hide": 1
},
{
"depends_on": "price_list_name",
"depends_on": "buying_price_list",
"doctype": "DocField",
"fieldname": "price_list_currency",
"fieldtype": "Link",
@ -228,7 +228,7 @@
"read_only": 1
},
{
"depends_on": "price_list_name",
"depends_on": "buying_price_list",
"doctype": "DocField",
"fieldname": "plc_conversion_rate",
"fieldtype": "Float",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-05-24 19:29:06",
"docstatus": 0,
"modified": "2013-07-25 16:32:51",
"modified": "2013-08-07 14:44:12",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -103,7 +103,6 @@
"width": "300px"
},
{
"default": "0.00",
"doctype": "DocField",
"fieldname": "qty",
"fieldtype": "Float",
@ -185,7 +184,6 @@
"read_only": 0
},
{
"default": "0.00",
"doctype": "DocField",
"fieldname": "purchase_rate",
"fieldtype": "Currency",
@ -201,7 +199,6 @@
"width": "100px"
},
{
"default": "0.00",
"doctype": "DocField",
"fieldname": "amount",
"fieldtype": "Currency",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-04-30 13:13:03",
"docstatus": 0,
"modified": "2013-07-05 14:52:20",
"modified": "2013-08-08 14:22:07",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -62,7 +62,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Naming Series",
"label": "Document Numbering Series",
"no_copy": 1,
"options": "\nQAI/11-12/",
"reqd": 1

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:11",
"docstatus": 0,
"modified": "2013-07-05 14:57:04",
"modified": "2013-08-08 14:22:08",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -82,7 +82,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"label": "Document Numbering Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",

View File

@ -10,7 +10,7 @@ class DocType(BuyingController):
def __init__(self, doc, doclist=None):
self.doc, self.doclist = doc, doclist or []
self.tname, self.fname = "Supplier Quotation Item", "quotation_items"
def validate(self):
super(DocType, self).validate()

View File

@ -2,7 +2,7 @@
{
"creation": "2013-05-21 16:16:45",
"docstatus": 0,
"modified": "2013-08-01 16:49:33",
"modified": "2013-08-09 14:45:58",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -52,7 +52,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"label": "Document Numbering Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
@ -208,14 +208,14 @@
{
"description": "Consider this Price List for fetching rate. (only which have \"For Buying\" as checked)",
"doctype": "DocField",
"fieldname": "price_list_name",
"fieldname": "buying_price_list",
"fieldtype": "Link",
"label": "Price List",
"options": "Price List",
"print_hide": 1
},
{
"depends_on": "price_list_name",
"depends_on": "buying_price_list",
"doctype": "DocField",
"fieldname": "price_list_currency",
"fieldtype": "Link",
@ -225,7 +225,7 @@
"read_only": 1
},
{
"depends_on": "price_list_name",
"depends_on": "buying_price_list",
"doctype": "DocField",
"fieldname": "plc_conversion_rate",
"fieldtype": "Float",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-05-22 12:43:10",
"docstatus": 0,
"modified": "2013-07-10 14:54:23",
"modified": "2013-08-07 14:44:18",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -87,7 +87,6 @@
"label": "Quantity and Rate"
},
{
"default": "0.00",
"doctype": "DocField",
"fieldname": "qty",
"fieldtype": "Float",
@ -169,7 +168,6 @@
"read_only": 0
},
{
"default": "0.00",
"doctype": "DocField",
"fieldname": "purchase_rate",
"fieldtype": "Currency",
@ -185,7 +183,6 @@
"width": "100px"
},
{
"default": "0.00",
"doctype": "DocField",
"fieldname": "amount",
"fieldtype": "Currency",

View File

@ -111,9 +111,14 @@ wn.module_page["Buying"] = [
icon: "icon-list",
items: [
{
"label":wn._("Item-wise Purchase History"),
route: "query-report/Item-wise Purchase History",
doctype: "Item"
"label":wn._("Requested Items To Be Ordered"),
route: "query-report/Requested Items To Be Ordered",
doctype: "Material Request"
},
{
"label":wn._("Material Requests for which Supplier Quotations are not created"),
route: "query-report/Material Requests for which Supplier Quotations are not created",
doctype: "Material Request"
},
{
"label":wn._("Purchase In Transit"),
@ -121,20 +126,20 @@ wn.module_page["Buying"] = [
doctype: "Purchase Order"
},
{
"label":wn._("Requested Items To Be Ordered"),
route: "query-report/Requested Items To Be Ordered",
doctype: "Material Request"
"label":wn._("Item-wise Purchase History"),
route: "query-report/Item-wise Purchase History",
doctype: "Item"
},
{
"label":wn._("Item-wise Last Purchase Rate"),
route: "query-report/Item-wise Last Purchase Rate",
doctype: "Item"
},
{
"label":wn._("Purchase Order Trends"),
route: "query-report/Purchase Order Trends",
doctype: "Purchase Order"
},
{
"label":wn._("Item-wise Last Purchase Rate"),
route: "query-report/Item-wise Last Purchase Rate",
doctype: "Item"
}
]
}
]

View File

@ -18,7 +18,7 @@ def get_item_details(args):
"supplier": None,
"transaction_date": None,
"conversion_rate": 1.0,
"price_list_name": None,
"buying_price_list": None,
"price_list_currency": None,
"plc_conversion_rate": 1.0,
"is_subcontracted": "Yes" / "No"
@ -88,10 +88,10 @@ def _get_price_list_rate(args, item_bean, meta):
out = webnotes._dict()
# try fetching from price list
if args.price_list_name and args.price_list_currency:
if args.buying_price_list and args.price_list_currency:
price_list_rate = item_bean.doclist.get({
"parentfield": "ref_rate_details",
"price_list_name": args.price_list_name,
"price_list": args.buying_price_list,
"ref_currency": args.price_list_currency,
"buying_or_selling": "Buying"})
if price_list_rate:

View File

@ -55,10 +55,11 @@ class AccountsController(TransactionBase):
def set_price_list_currency(self, buying_or_selling):
company_currency = get_company_currency(self.doc.company)
fieldname = buying_or_selling.lower() + "_price_list"
# TODO - change this, since price list now has only one currency allowed
if self.meta.get_field("price_list_name") and self.doc.price_list_name and \
if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname) and \
not self.doc.price_list_currency:
self.doc.fields.update(get_price_list_currency(self.doc.price_list_name))
self.doc.fields.update(get_price_list_currency(self.doc.fields.get(fieldname)))
if self.doc.price_list_currency:
if not self.doc.plc_conversion_rate:
@ -73,11 +74,14 @@ class AccountsController(TransactionBase):
self.doc.currency = self.doc.price_list_currency
self.doc.conversion_rate = self.doc.plc_conversion_rate
if self.meta.get_field("currency") and self.doc.currency != company_currency and \
not self.doc.conversion_rate:
exchange = self.doc.currency + "-" + company_currency
self.doc.conversion_rate = flt(webnotes.conn.get_value("Currency Exchange",
exchange, "exchange_rate"))
if self.meta.get_field("currency"):
if self.doc.currency and self.doc.currency != company_currency:
if not self.doc.conversion_rate:
exchange = self.doc.currency + "-" + company_currency
self.doc.conversion_rate = flt(webnotes.conn.get_value("Currency Exchange",
exchange, "exchange_rate"))
else:
self.doc.conversion_rate = 1
def set_missing_item_details(self, get_item_details):
"""set missing item values"""
@ -261,7 +265,7 @@ class AccountsController(TransactionBase):
tax.grand_total_for_current_item = \
flt(self.tax_doclist[i-1].grand_total_for_current_item +
current_tax_amount, self.precision("total", tax))
# in tax.total, accumulate grand total of each item
tax.total += tax.grand_total_for_current_item
@ -388,7 +392,7 @@ class AccountsController(TransactionBase):
total_billed_amt = flt(flt(already_billed) + flt(item.fields[based_on]),
self.precision(based_on, item))
if max_allowed_amt and total_billed_amt - max_allowed_amt > 0.02:
webnotes.msgprint(_("Row ")+ cstr(item.idx) + ": " + cstr(item.item_code) +
_(" will be over-billed against mentioned ") + cstr(ref_dt) +

View File

@ -30,6 +30,7 @@ class BuyingController(StockController):
def set_missing_values(self, for_validate=False):
super(BuyingController, self).set_missing_values(for_validate)
self.set_supplier_from_item_default()
self.set_price_list_currency("Buying")
# set contact and address details for supplier, if they are not mentioned
@ -40,6 +41,14 @@ class BuyingController(StockController):
self.set_missing_item_details(get_item_details)
def set_supplier_from_item_default(self):
if self.meta.get_field("supplier") and not self.doc.supplier:
for d in self.doclist.get({"doctype": self.tname}):
supplier = webnotes.conn.get_value("Item", d.item_code, "default_supplier")
if supplier:
self.doc.supplier = supplier
break
def get_purchase_tax_details(self):
self.doclist = self.doc.clear_table(self.doclist, "purchase_tax_details")
self.set_taxes("purchase_tax_details", "purchase_other_charges")
@ -89,7 +98,7 @@ class BuyingController(StockController):
if item.discount_rate == 100.0:
item.import_rate = 0.0
elif item.import_ref_rate:
elif not item.import_rate:
item.import_rate = flt(item.import_ref_rate * (1.0 - (item.discount_rate / 100.0)),
self.precision("import_rate", item))

View File

@ -16,11 +16,14 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) {
if(doc.__islocal) {
var last_route = wn.route_history.slice(-2, -1)[0];
if(last_route && last_route[0]==="Form") {
var doctype = last_route[1],
docname = last_route.slice(2).join("/");
if(["Customer", "Quotation", "Sales Order", "Sales Invoice", "Delivery Note",
"Installation Note", "Opportunity", "Customer Issue", "Maintenance Visit",
"Maintenance Schedule"]
.indexOf(last_route[1])!==-1) {
var refdoc = wn.model.get_doc(last_route[1], last_route[2]);
.indexOf(doctype)!==-1) {
var refdoc = wn.model.get_doc(doctype, docname);
if(refdoc.doctype == "Quotation" ? refdoc.quotation_to=="Customer" : true) {
cur_frm.set_value("customer", refdoc.customer || refdoc.name);
@ -30,16 +33,16 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) {
}
}
if(["Supplier", "Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"]
.indexOf(last_route[1])!==-1) {
var refdoc = wn.model.get_doc(last_route[1], last_route[2]);
.indexOf(doctype)!==-1) {
var refdoc = wn.model.get_doc(doctype, docname);
cur_frm.set_value("supplier", refdoc.supplier || refdoc.name);
cur_frm.set_value("supplier_name", refdoc.supplier_name);
if(cur_frm.doc.doctype==="Address")
cur_frm.set_value("address_title", cur_frm.doc.supplier_name);
}
if(["Lead", "Quotation"]
.indexOf(last_route[1])!==-1) {
var refdoc = wn.model.get_doc(last_route[1], last_route[2]);
.indexOf(doctype)!==-1) {
var refdoc = wn.model.get_doc(doctype, docname);
if(refdoc.doctype == "Quotation" ? refdoc.quotation_to=="Lead" : true) {
cur_frm.set_value("lead", refdoc.lead || refdoc.name);

View File

@ -187,10 +187,10 @@ def get_project_name(doctype, txt, searchfield, start, page_len, filters):
def get_price_list_currency(doctype, txt, searchfield, start, page_len, filters):
return webnotes.conn.sql("""select ref_currency from `tabItem Price`
where price_list_name = %s and buying_or_selling = %s
where price_list = %s and buying_or_selling = %s
and `%s` like %s order by ref_currency asc limit %s, %s""" %
("%s", "%s", searchfield, "%s", "%s", "%s"),
(filters["price_list_name"], filters['buying_or_selling'], "%%%s%%" % txt,
(filters["price_list"], filters['buying_or_selling'], "%%%s%%" % txt,
start, page_len))
def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters):
@ -207,4 +207,4 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len,
"fcond": get_filters_cond(doctype, filters, []),
"mcond": get_match_cond(doctype),
"start": "%(start)s", "page_len": "%(page_len)s", "txt": "%(txt)s"
}, { "start": start, "page_len": page_len, "txt": ("%%%s%%" % txt) }, debug=True)
}, { "start": start, "page_len": page_len, "txt": ("%%%s%%" % txt) })

View File

@ -14,12 +14,8 @@ class SellingController(StockController):
def onload_post_render(self):
# contact, address, item details and pos details (if applicable)
self.set_missing_values()
self.set_taxes("other_charges", "charge")
if self.meta.get_field("debit_to") and not self.doc.debit_to:
self.doc.debit_to = self.get_debit_to().get("debit_to")
def set_missing_values(self, for_validate=False):
super(SellingController, self).set_missing_values(for_validate)
@ -104,8 +100,8 @@ class SellingController(StockController):
for item in self.doclist.get({"parentfield": self.fname}):
if item.item_code in stock_items or \
(item_sales_bom and item_sales_bom.get(item.item_code)):
buying_amount = get_buying_amount(item.item_code, item.warehouse, -1*item.qty,
self.doc.doctype, self.doc.name, item.name, stock_ledger_entries,
buying_amount = get_buying_amount(item.item_code, self.doc.doctype, self.doc.name, item.name,
stock_ledger_entries.get((item.item_code, item.warehouse), []),
item_sales_bom)
item.buying_amount = buying_amount >= 0.01 and buying_amount or 0
webnotes.conn.set_value(item.doctype, item.name, "buying_amount",
@ -191,7 +187,7 @@ class SellingController(StockController):
if item.adj_rate == 100:
item.export_rate = 0
elif item.ref_rate:
elif not item.export_rate:
item.export_rate = flt(item.ref_rate * (1.0 - (item.adj_rate / 100.0)),
self.precision("export_rate", item))

View File

@ -87,11 +87,13 @@ class StockController(AccountsController):
get_obj('Stock Ledger').update_stock(sl_entries, is_amended)
def get_stock_ledger_entries(self, item_list=None, warehouse_list=None):
out = {}
if not (item_list and warehouse_list):
item_list, warehouse_list = self.get_distinct_item_warehouse()
if item_list and warehouse_list:
return webnotes.conn.sql("""select item_code, voucher_type, voucher_no,
res = webnotes.conn.sql("""select item_code, voucher_type, voucher_no,
voucher_detail_no, posting_date, posting_time, stock_value,
warehouse, actual_qty as qty from `tabStock Ledger Entry`
where ifnull(`is_cancelled`, "No") = "No" and company = %s
@ -100,6 +102,14 @@ class StockController(AccountsController):
posting_time desc, name desc""" %
('%s', ', '.join(['%s']*len(item_list)), ', '.join(['%s']*len(warehouse_list))),
tuple([self.doc.company] + item_list + warehouse_list), as_dict=1)
for r in res:
if (r.item_code, r.warehouse) not in out:
out[(r.item_code, r.warehouse)] = []
out[(r.item_code, r.warehouse)].append(r)
return out
def get_distinct_item_warehouse(self):
item_list = []

View File

@ -122,7 +122,7 @@ in ERPNext.
"plc_conversion_rate": 1.0,
"posting_date": "2013-01-23",
"price_list_currency": "INR",
"price_list_name": "_Test Price List",
"selling_price_list": "_Test Price List",
"territory": "_Test Territory"
},

View File

@ -1,25 +0,0 @@
---
{
"_label": "ERPNext Pre-requisites for Debian systems (Unbuntu)"
}
---
#### If not root user
`sudo su`
#### Installing Pre-Requisites
cd ~
apt-get install python python-setuptools python-mysqldb apache2 mysql-server libmysqlclient-dev git memcached -y
easy_install pip
pip install pytz python-dateutil jinja2 markdown2 termcolor python-memcached requests chardet dropbox google-api-python-client pygeoip
a2enmod rewrite
service apache2 start
service mysql start
memcached -d -l 127.0.0.1 -p 11211 -m 64 -u www-data
> ```memcached -d -l 127.0.0.1 -p 11211 -m [64 or more mb of ram] -u apache ```
#### Other useful programs
apt-get install ntp vim screen htop -y
service ntpd start

View File

@ -2,8 +2,7 @@
{
"_label": "How to Install ERPNext",
"_toc": [
"docs.dev.install.red_hat",
"docs.dev.install.debian"
"docs.dev.install.restore_from_backup"
]
}
---
@ -15,8 +14,8 @@
Install ERPNext in one command!
1. Switch to root user using `sudo su`
1. create a folder where you want to install erpnext
1. go to the new folder
1. Create a folder where you want to install erpnext
1. Go to the new folder
1. `wget https://raw.github.com/webnotes/erpnext/master/install_erpnext.py`
1. `python install_erpnext.py`
@ -24,133 +23,19 @@ Install ERPNext in one command!
> If you get stuck, post your questions at [ERPNext Developer Forum](https://groups.google.com/forum/#!forum/erpnext-developer-forum)
> [Troubleshooting SELinux](http://www.crypt.gen.nz/selinux/disable_selinux.html)
--
> [Server Setup Tips](http://plusbryan.com/my-first-5-minutes-on-a-server-or-essential-security-for-linux-servers)
> [MySQL configuration file - my.cnf](MySQL-configuration-file)
> [MySQL configuration file - my.cnf](https://github.com/webnotes/erpnext/wiki/MySQL-configuration-file)
> [Some Useful Aliases](Some-Useful-Aliases)
> [Some Useful Aliases](https://github.com/webnotes/erpnext/wiki/Some-Useful-Aliases)
---
### Upgrade / run latest patches
1. Backup your database!
1. go to Setup > Update This Application [under Update Manager]
1. click on 'Get Latest Updates'
> [Restoring from ERPNext backup](Restoring-From-ERPNext-Backup)
---
### Step by step instructions
1. You will need some linux background to be able to install this on your system.
1. These are high-level instructions and by no means cover every installation issue.
### Pre-requisites:
* any unix based os
* python 2.6+ (python 3+ not supported)
* apache
* mysql 5+
* git
* python libraries:
* python MySQLdb
* pytz
* jinja2
* markdown2
* dateutil
* termcolor
* python-memcached
* requests
* chardet
* pygeoip
* dropbox
* google-api-python-client
* memcached
## Fresh Installation
### Steps: [using terminal]
#### Get the Install Script
Download the standard install script and install. This script will:
- Create `app` and `lib` folders.
- Clone the code repositories for `wnframework` and `erpnext` from GitHub. It is important to clone the repositories from GitHub rather than just downloading the code, because this will help you in upgrading the system.
- Create the database.
- Create a default `erpnext.conf` Apache configuration file for ERPnext.
- Create the standard wnframework configuration file `conf.py`
- Build the `public` folder from which the ERPNext client application will be served via Apache and CGI.
**Instructions**
1. ensure mysql service is running
1. create a folder where you want to install erpnext
1. go to the new folder
1. `wget https://github.com/webnotes/erpnext/blob/master/install_erpnext.py`
1. `python install_erpnext.py`
#### Setup Apache
1. check your apache/httpd user and group. Most often it is either `apache` or `_www`. This can be found in its conf file.
1. run `chown -R apache:apache *` or `chown -R _www:_www *`. This will make the erpnext folder accessible to apache webserver.
1. create erpnext.conf file in erpnext folder and paste a modified version of apache configuration file as shown in the example below. (You will need to change the values in square brackets)
* For debian systems, `sudo ln -s [PATH TO ERPNEXT INSTALLATION]/erpnext.conf /etc/apache2/sites-enabled/erpnext.conf`
* For redhat systems, `sudo ln -s [PATH TO ERPNEXT INSTALLATION]/erpnext.conf /etc/httpd/conf.d/erpnext.conf`
1. restart apache service
1. if firewall exists, run
```
iptables -I INPUT 1 -p tcp --dport 8080 -j ACCEPT
service iptables save
```
### Setup Schueduler
1. setup cron using `crontab -e` and enter the following and then save it:
```
*/3 * * * * cd [PATH TO ERPNEXT INSTALLATION] && python lib/wnf.py --run_scheduler >> /var/log/erpnext-sch.log 2>&1
0 */6 * * * cd [PATH TO ERPNEXT INSTALLATION] && python lib/wnf.py --backup >> /var/log/erpnext-backup.log 2>&1
```
### Start
1. go to erpnext folder and run `lib/wnf.py --domain localhost:8080`
1. start your browser and go to http://localhost:8080
1. login as user: Administrator and password: admin
> If you are installing on your server for deployment, remember to change Administrator's password!
### What to write in apache configuration file?
Listen 8080
NameVirtualHost *:8080
<VirtualHost *:8080>
ServerName localhost
DocumentRoot [PATH TO ERPNEXT INSTALLATION]/public/
AddHandler cgi-script .cgi .xml .py
AddType application/vnd.ms-fontobject .eot
AddType font/ttf .ttf
AddType font/otf .otf
AddType application/x-font-woff .woff
<Directory [PATH TO ERPNEXT INSTALLATION]/public/>
# directory specific options
Options -Indexes +FollowSymLinks +ExecCGI
# directory's index file
DirectoryIndex web.py
AllowOverride all
Order Allow,Deny
Allow from all
# rewrite rule
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^([^/]+)$ /web.py?page=$1 [QSA,L]
</Directory>
</VirtualHost>
1. Go to Setup > Update ERPNext
1. Click on 'Update'

View File

@ -1,59 +0,0 @@
---
{
"_label": "ERPNext Pre-requisites for Red Hat systems (CentOS, Fedora)"
}
---
#### If not root user
`sudo su`
#### Installing Pre-Requisites
cd ~
yum update python -y
yum install python-setuptools MySQL-python httpd mysql mysql-server mysql-devel git memcached ntp vim -y
easy_install pip
pip install pytz python-dateutil jinja2 markdown2 termcolor python-memcached requests chardet dropbox google-api-python-client pygeoip
service httpd start
service mysqld start
service ntpd start
mysqladmin -u root password [NEW PASSWORD]
#### memcached
1. `vim /etc/sysconfig/memcached`
1. change user to the apache user, change the cache size if desired (depending on available memory), save the file
1. `service memcached start`
#### set services to run when machine starts
chkconfig --level 2345 mysql on
chkconfig --level 2345 httpd on
chkconfig --level 2345 memcached on
chkconfig --level 2345 ntpd on
#### Other useful programs
wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm
rpm -i http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm
yum install htop screen -y
--
#### CPanel Users
If you are using CPanel, you are likely to face perl dependency issues when installing git. To install git in this case, follow this procedure:
1. `vim /etc/yum.conf`, remove perl* from exclude list and save the file
1. `yum install git -y`
1. `vim /etc/yum.conf`, add perl* back to exclude list and save the file
> source: [http://forums.cpanel.net/f5/upcp-errors-due-dependeny-problems-centos-6-3-not-upgraded-centos-6-4-a-332102.html](http://forums.cpanel.net/f5/upcp-errors-due-dependeny-problems-centos-6-3-not-upgraded-centos-6-4-a-332102.html)
CPanel users should follow these steps to set the apache configuration for ERPNext:
1. `vim /etc/httpd/conf/includes/post_virtualhost_2.conf`
1. add the line `Include [PATH TO ERPNEXT CONF FILE]` (example: /var/www/erpnext.conf) and save the file
1. `vim [PATH TO ERPNEXT CONF FILE]`, set the apache configuration for ERPNext and save it
1. `service httpd restart`
*The mysql root password may be found at* `/root/.my.cnf`

View File

@ -0,0 +1,26 @@
---
{
"_label": "Restoring From ERPNext Backup"
}
---
* Download backup files
cd /tmp
wget [DATABASE BACKUP FILE URL]
wget [FILES BACKUP FILE URL]
* Suppose your backup files are downloaded at /tmp
gunzip [DATABASE BACKUP FILE.sql.gz]
tar xvf [FILES BACKUP.tar]
* Go to your ERPNext installation folder
* When restoring from database, the 'Administrator' user password gets reset to 'admin'. To set a better password when restoring, set admin_password variable in conf.py to the desired 'Administrator' user password.
* Restore database using:
lib/wnf.py --install [DATABASE NAME] /tmp/[DATABASE BACKUP FILE.sql]
* Copy extracted files
cp /tmp/[FILES BACKUP EXTRACTED FOLDER/---/public/files/*] [YOUR ERPNEXT INSTALLATION]/public/files/

View File

@ -22,13 +22,13 @@
### What is ERPNext?
ERPNext is an information system that links together entire organization's operations. It is a software package that offers convenience of managing all the business functions from a single platform. No need of going to different applications to process different requests. No need of saving data in different functional packages. Under one ERP "roof" you can manage Accounting, Warehouse Management, CRM, Human Resources, Supply Chain Management, Sales Management, and Website Design.
ERPNext is an information system that links together an entire organization's operations. It is a software package that offers convenience of managing all the business functions from a single platform. No need of going to different applications to process different requests. No need of saving data in different functional packages. Under one ERP "roof" you can manage Accounting, Warehouse Management, CRM, Human Resources, Supply Chain Management, Sales Management, and Website Design.
ERPNext is written by Web Notes Technologies keeping small and medium businesses in mind.
ERPNext is written by Web Notes Technologies keeping small and medium businesses in mind.
- It gives better access to crucial information as a whole rather than in fragments of different versions.
- It provides comparable financial reports.
- It avoids duplication of reports and redundant data.
- It allows better alignment across cross-functional departments.
- It facilitates Website Design and provides shopping cart facility.
- It gives better deployment on mobiles, tablets, desktops and large screens.
- It gives better deployment on mobiles, tablets, desktops and large screens.

View File

@ -32,7 +32,7 @@ A look at some of the common accounting entries that can be done via Journal Vou
#### Expenses (non accruing)
Many times it may not be necessary to accrue an expense, but it can be directly be booked against an expense Account on payment. For example a travel allowance or a telephone bill. You can directly debit Telephone Expense (instead of your telephone company) and credit your Bank on payment.
Many times it may not be necessary to accrue an expense, but it can be directly booked against an expense Account on payment. For example a travel allowance or a telephone bill. You can directly debit Telephone Expense (instead of your telephone company) and credit your Bank on payment.
- Debit: Expense Account (like Telephone expense)
- Credit: Bank or Cash Account

View File

@ -42,7 +42,7 @@ To use this, go to:
Select your “Bank” Account and enter the dates of your statement. Here you will get all the “Bank Voucher” type entries. In each of the entry on the right most column, update the “Clearance Date” and click on “Update”.
This way you will be able sync your bank statements and entries in the system.
This way you will be able to sync your bank statements and entries in the system.
---

View File

@ -22,10 +22,10 @@ The sum of all closing balances in a Trial Balance must be zero.
### Accounts Payable and Accounts Receivable (AP / AR)
These reports help you track the outstanding invoices to Customer and Suppliers. In this report, you will get your outstanding amounts period wise. i.e. between 0-30 days, 30-60 days and so on.
These reports help you to track the outstanding invoices sent to Customer and Suppliers. In this report, you will get your outstanding amounts period wise. i.e. between 0-30 days, 30-60 days and so on.
You can also get your payables and receivables from direct reports on Sales Invoice and Purchase Invoice.
### Sales and Purchase Register
This is useful for making your tax statements invoice and Item wise. In this report, each tax Account is transposed in columns and for each Invoice and invoice Item, you will get how much individual tax has been paid based on the Taxes and Charges table.
This is useful for making your tax statements invoice and Item wise. In this report, each tax Account is transposed in columns and for each Invoice and invoice Item, you will get the amount of individual tax that has been paid based on the Taxes and Charges table.

View File

@ -9,8 +9,8 @@ A Material Request can be generated:
- By a User.
- Automatically from a Sales Order.
- Automatically when the Projected Quantity (more on this later) of an Item in stores reaches a particular level.
- Automatically from your Bill of Materials if you use Production Plan to plan your manufacturing. (more on this later too)
- Automatically when the Projected Quantity of an Item in stores reaches a particular level.
- Automatically from your Bill of Materials if you use Production Plan to plan your manufacturing activities.
To generate a Material Request manually go to:
@ -19,7 +19,7 @@ To generate a Material Request manually go to:
In the Material Request form,
- Fill in the Items you want and their quantities.
- If your Items are inventory items, you must also mention the Warehouse where you expect these Items to be delivered to. This helps you to keep track of the Projected Quantity for this Item.
- If your Items are inventory items, you must also mention the Warehouse where you expect these Items to be delivered. This helps to keep track of the Projected Quantity for this Item.
- You can also automatically get the Items from a Sales Order.
- You can optionally add the Terms, using the Terms and Conditions master and also the reason.

View File

@ -3,8 +3,8 @@
"_label": "Buying"
}
---
If your business involves physical goods, buying is one of your core business activities. Your suppliers are as important as your customers and they must be provided with as much accurate information as possible.
If your business involves physical goods, buying is one of your core business activity. Your suppliers are as important as your customers and they must be provided with as much accurate information as possible.
Buying in right amounts at right quantities can affect your cash flow and profitability.
Buying in right amounts, in right quantities, can affect your cash flow and profitability.
ERPNext contains a set of transactions that will make your buying as efficient and seamless as possible.
ERPNext contains a set of transactions that will make your buying process as efficient and seamless as possible.

View File

@ -3,7 +3,7 @@
"_label": "Purchase Order"
}
---
A Purchase Order is analogous to a Sales Order. It is usually a binding contract with your Supplier that you promise to buy this set of Items under the given conditions.
A Purchase Order is analogous to a Sales Order. It is usually a binding contract with your Supplier that you promise to buy a set of Items under the given conditions.
In ERPNext, you can make a Purchase Order by going to:
@ -14,16 +14,16 @@ A Purchase Order can also be automatically created from a Purchase Request or S
Entering a Purchase Order is very similar to a Purchase Request, additionally you will have to set:
- Supplier.
- A “Required By” date on each Item: If you are expecting part delivery, your Supplier will know how much quantity to deliver at which date. This will help you from preventing over-supply. It will also help you track how well your Supplier is doing on timeliness.
- A “Required By” date on each Item: If you are expecting part delivery, your Supplier will know how much quantity to deliver at which date. This will help you from preventing over-supply. It will also help you to track how well your Supplier is doing on timeliness.
### Taxes
If your Supplier is going to charge you additional taxes or charge like a shipping or insurance charge, you can add it here. It will help you to accurately track your costs. Also if some of these charges add to the value of the product you will have to mention in the Taxes table. You can also use templates for your taxes. For more information on setting up your taxes see the Purchase Taxes and Charges Master.
If your Supplier is going to charge you additional taxes or charge like a shipping or insurance charge, you can add it here. It will help you to accurately track your costs. Also, if some of these charges add to the value of the product you will have to mention them in the Taxes table. You can also use templates for your taxes. For more information on setting up your taxes see the Purchase Taxes and Charges Master.
### Value Added Taxes (VAT)
Many times, the tax paid by you to a Supplier for an Item is the same tax you collect from your Customer. In many regions, what you pay to your government is only the difference between what you collect from your Customer and pay to your Supplier. This is called Value Added Tax (VAT).
Many a times, the tax paid by you to a Supplier, for an Item, is the same tax which you collect from your Customer. In many regions, what you pay to your government is only the difference between what you collect from your Customer and what you pay to your Supplier. This is called Value Added Tax (VAT).
For example you buy Items worth X and sell them for 1.3X. So your Customer pays 1.3 times the tax you pay your Supplier. Since you have already paid tax to your Supplier for X, what you owe your government is only the tax on 0.3X.

View File

@ -8,10 +8,10 @@ Suppliers are companies or individuals who provide you with products or services
1. Separate Account Ledgers are created for the Supplier in the Company under “Accounts Payable”.
1. You can have multiple Addresses and Contacts for Suppliers.
1. Suppliers are categorized as Supplier Type.
1. If you set “Credit Days”, this will automatically set the due date in Purchase Invoices.
1. If you set “Credit Days”, ERPNext will automatically set the due date in Purchase Invoices.
You can create a new Supplier via:
> Buying > Supplier > New Supplier
or importing from the Data Import Tool
or import from the Data Import Tool

View File

@ -8,7 +8,7 @@ If you have multiple **Suppliers** who supply you with the same **Item**, you us
- You can easily compare prices in the future
- Audit whether all Suppliers were given the opportunity to quote.
Supplier Quotations are not necessary for most small businesses. Always evaluate the cost of collecting information to the value it provides! You could only do this for high value items.
Supplier Quotations are not necessary for most small businesses. Always evaluate the cost of collecting information to the value it really provides! You could only do this for high value items.
You can make a Supplier Quotation directly from:

View File

@ -11,7 +11,7 @@ In the form:
- Select the Document on which you want to add the Custom Field.
- Select the Type of field and the Options (see section on field types).
- Select where you want to field to appear in the Form (“after field” section).
- Select where you want the field to appear in the Form (“after field” section).
and save the Custom Field. When you open a new / existing form of the type you selected in step 1, you will see it with the Custom Fields.

View File

@ -5,7 +5,7 @@
---
### Hiding Unused Features
As you have seen from this manual that ERPNext contains tons of feature that you may not use. We have observed that most users start with using 20% of the features, though a different 20%. To hide fields belonging to features you will not use, go to:
As you have seen from this manual that ERPNext contains tons of features which you may not use. We have observed that most users start with using 20% of the features, though a different 20%. To hide fields belonging to features you dont require, go to:
> Setup > Customize ERPNext > Disable Features.

View File

@ -6,7 +6,7 @@
Print Formats are the layouts that are generated when you want to Print or Email a transaction like a Sales Invoice. There are two types of Print Formats,
- The auto-generated “Standard” Print Format: This type of format follows the same layout as the form and is generated automatically by ERPNext.
- Based on the Print Format document. This is templates in HTML that will be rendered with data.
- Based on the Print Format document. There are templates in HTML that will be rendered with data.
ERPNext comes with a number of pre-defined templates in three styles: Modern, Classic and Spartan. You modify these templates or create their own. Editing ERPNext templates is not allowed because they may be over-written in an upcoming release.

View File

@ -3,7 +3,7 @@
"_label": "Appraisal"
}
---
In ERPNext, you can manage Employee Appraisals by creating an Appraisal Template for each role with the parameters that define the performance and giving a weight to each parameter.
In ERPNext, you can manage Employee Appraisals by creating an Appraisal Template for each role with the parameters that define the performance by giving appropriate weightage to each parameter.
Once the Appraisal Template is completed, you can create Appraisal records for each period where you track performance. You can give points out of 5 for each parameter and the system will calculate the overall performance of the Employee.

View File

@ -3,7 +3,7 @@
"_label": "Expense Claim"
}
---
When Employees make expenses out their pocket on behalf of the company, like if they took a customer out for lunch, they can make a request for reimbursement via the Expense Claim form.
When Employees make expenses out of their pocket on behalf of the company, for example, if they take a customer out for lunch, they can make a request for reimbursement via the Expense Claim form.
To make a new Expense Claim, go to:
@ -21,4 +21,4 @@ Comments can be added in the Comments section explaining why the claim was appro
### Booking the Expense and Reimbursement
The approved Expense Claim must be then be converted into a Journal Voucher and a payment must be made. Note: This amount should not be clubbed with Salary because the amount will then be taxable to the Employee.
The approved Expense Claim must then be converted into a Journal Voucher and a payment must be made. Note: This amount should not be clubbed with Salary because the amount will then be taxable to the Employee.

View File

@ -3,7 +3,7 @@
"_label": "Human Resource Management"
}
---
The Human Resources (HR) Module covers the processes linked to administering a team of co-workers. Most common among this is processing payroll by using the Salary Manager to generate Salary Slips. Most countries have complex tax rules stating what expenses can the company made on behalf of Employees and also expect the company to deduct taxes and social security from their payroll.
The Human Resources (HR) Module covers the processes linked to administering a team of co-workers. Most common among this is processing payroll by using the Salary Manager to generate Salary Slips. Most countries have complex tax rules stating what expenses can the company make on behalf of Employees and also expect the company to deduct taxes and social security from their payroll.
Apart from that you can also track Leave Applications and balances, Expense Claims and upload Attendance data (even though the world has moved to a result-oriented culture, some countries still mandate companies to maintain an attendance register to ensure you are not over-working your team).

View File

@ -10,7 +10,7 @@ The Manufacturing module in ERPNext helps you maintain multi-level Bill of Mater
Broadly there are three types of Production Planning Systems
- Make-to-Stock: In these systems, production is planned based on a forecast and then the Items are sold to distributors or customers. All fast moving consumer goods that are sold in retail shops like soaps, packaged water etc and electronics like phones etc are Made to Stock.
- Make-to-Order: In these systems, manufacturing takes place after an firm order is placed by a Customer.
- Make-to-Order: In these systems, manufacturing takes place after a firm order is placed by a Customer.
- Engineer-to-Order: In this case each sale is a separate Project and has to be designed and engineered to the requirements of the Customer. Common examples of this are any custom business like furniture, machine tools, speciality devices, metal fabrication etc.
Most small and medium sized manufacturing businesses are based on a make-to-order or engineer-to-order system and so is ERPNext.
@ -42,7 +42,7 @@ The state of art manufacturing philosophy (the rationale behind the planning pro
The biggest cause of wastage in manufacturing is variation (in product and quantity).
So they standardized their products and sub-assemblies and sold fixed quantities based on what they produced not produce based on what they sold. This way, they had an extremely predictable and stable product mix. If they sold less than planned, they would simple stop production.
So they standardized their products and sub-assemblies and sold fixed quantities based on what they produced or did not produce based on what they sold. This way, they had an extremely predictable and stable product mix. If they sold less than planned, they would simply stop production.
Their card signaling system kanban, would notify all their suppliers to stop production too. Hence they never used any of the complex material planning tools like MRP to play day-to-day material requirements, but a simple signaling system that said either STOP or GO.

View File

@ -3,7 +3,7 @@
"_label": "Production Order"
}
---
Production Order (also called as Work Order) is a document that is given to the manufacturing shop floor by the Production Planner as a signal to product a certain quantity of a certain Item. Production Order also helps to generate the material requirements (Stock Entry) for the Item to be produced from its **Bill of Materials**.
Production Order (also called as Work Order) is a document that is given to the manufacturing shop floor by the Production Planner as a signal to produce a certain quantity of a certain Item. Production Order also helps to generate the material requirements (Stock Entry) for the Item to be produced from its **Bill of Materials**.
The **Production Order** is generated directly from the **Production Planning Tool** based on Sales Orders. You can also create a direct Production Order by:
@ -13,7 +13,7 @@ The **Production Order** is generated directly from the **Production Planning To
- Select the BOM
- Select Quantities
- Select Warehouses. WIP (Work-in-Progress) is where your Items will be transferred when you begin production and FG (Finished Goods) where you store finished Items before they are shipped.
- Select if you want to consider sub-assemblies (sub-Items that have their own BOM) as stock items or you want to explode the entire BOM when you make Stock Entries for this Item. What is means is that if you also maintain stock of your sub assemblies then you should set this as “No” and in your Stock Entires, it will also list the sub-assembly Item (not is sub-components).
- Select if you want to consider sub-assemblies (sub-Items that have their own BOM) as stock items or you want to explode the entire BOM when you make Stock Entries for this Item. What it means is that if you also maintain stock of your sub assemblies then you should set this as “No” and in your Stock Entires, it will also list the sub-assembly Item (not is sub-components).
and “Submit” the Production Order.

View File

@ -10,7 +10,6 @@ You can either directly create your Customers via
or upload it via the Data Import Tool.
In your normal operations, you can also create Customers from Leads.
> Note: Customers are separate from Contacts and Addresses. A Customer can have multiple Contacts and Addresses.
@ -20,7 +19,7 @@ Contacts and Addresses in ERPNext are stored separately so that you can attach m
To add a Contact or Address directly from the Customer record, click on “New Contact” or “New Address”.
> Tip: When you select a Customer in any transaction, one Contact and Address gets pre-selected. This is the “Default Contact or Address”. So make sure you set your defaults correctly!
> Tip: When you select a Customer in any transaction, one Contact and Address gets pre-selected. This is the “Default Contact or Address”.
To Import multiple Contacts and Addresses from a spreadsheet, use the Data Import Tool.

View File

@ -15,7 +15,7 @@ The Chart of Accounts helps you answer:
- How much debt have you taken?
- How much profit are you making (and hence paying tax)?
- How much are you selling?
- How are your expenses broken up?
- What is your expense break- up
You may note that as a business manager,it is very valuable to see how well your business is doing.

View File

@ -3,16 +3,16 @@
"_label": "Item Codification"
}
---
If you already have a running business with a number of physical items, you would have probably coded your items. If you have not, you have a choice. We recommend you should codify, but its your call.
If you already have a full-fledged business with a number of physical items, you would have probably coded your items. If you have not, you have a choice. We recommend that you should codify if you have lot of products with long or complicated names. In case you have few products with short names, it is preferable to keep the Item Code same as Item Name.
Item codification is always a sensitive topic and wars have been fought on this (not joking). In our experience, when you have items that cross a certain size, life without codification is a nightmare.
Item codification has been a sensitive topic and wars have been fought on this (not joking). In our experience, when you have items that cross a certain size, life without codification is a nightmare.
### Benefits
- Standard way of naming things.
- Less likely to have duplicates.
- Explicit definition.
- Help you quickly find if a similar item exists.
- Helps to quickly find if a similar item exists.
- Item names get longer and longer as more types get introduced. Codes are shorter.
### Pain
@ -23,7 +23,7 @@ Item codification is always a sensitive topic and wars have been fought on this
### Example
You should have a simple manual / cheat-sheet to codify your items instead of just numbering them sequentially. Each letter should mean something. Here is an example:
You should have a simple manual / cheat-sheet to codify your Items instead of just numbering them sequentially. Each letter should mean something. Here is an example:
If your business involves wooden furniture, then you may codify as follows:
@ -52,7 +52,7 @@ The last few letters could be sequential. So by looking at code **WM304** - you
### Standardization
If you have more than one person naming items, the style of naming items will change for everyone. Sometimes, even for one person, he or she may forget how did they name the item and may create a duplicate name _"Wooden Sheet 3mm" or "3mm Sheet of Wood"?_
If you have more than one person naming items, the style of naming items will change for everyone. Sometimes, even for one person, he or she may forget how they had named the item and may create a duplicate name _"Wooden Sheet 3mm" or "3mm Sheet of Wood"?_
### Rationalizing

View File

@ -63,7 +63,7 @@ If you have multiple child rows then you must start a new main item on a new row
### 5. Overwriting
ERPNext also allows you to overwrite all / certain columns. If you want to update certain columns, you can download the template with data. Remember to check on the “Overwrite” box before uploading.
ERPNext also allows you to overwrite all / certain columns. If you want to update certain columns, you can download the template with data.Remember to check on the “Overwrite” box before uploading.
> Note: For child records, if you select Overwrite, it will delete all the child records of that parent.

View File

@ -27,7 +27,7 @@ Set your outgoing mail server settings here. These are the same settings you wou
A very useful email integration is to sync the incoming emails from support inbox into Support Ticket, so that you can track, assign and monitor support issues.
> **Case Study:** Here are ERPNext, we have regularly tracking incoming support issues via email at “support@erpnext.com”. At the time of writing we have answered more than 3000 tickets via this system.
> **Case Study:** Here at ERPNext, we have regularly tracked incoming support issues via email at “support@erpnext.com”. At the time of writing we had answered more than 3000 tickets via this system.
To setup your Support integration, go to:
@ -35,7 +35,7 @@ To setup your Support integration, go to:
To make ERPNext pull emails from your mail box, enter the POP3 settings. (POP3 is a way of extracting emails from your mailbox. It should be fairly easy to find out what your POP3 settings are. If you have problems, contact your email service provider).
If you want to setup an auto reply, check on the “Send Autoreply” box and whenever someone sends an email, an autoreply will be sent.
Add a custom signature you want to send with your replies.
Add a custom signature which you want to send with your replies.
### Setting Auto-notification on Documents
@ -49,7 +49,7 @@ Check on the transactions you want to send via email directly on Submission and
Email Digests allow you to get regular updates about your sales, expenses and other critical numbers directly in your Inbox.
Set your frequency, check all the items you want to receive in your weekly update and select the user ids who you want to send the Digest to.
Set your frequency, check all the items you want to receive in your weekly update and select the user ids whom you want to send the Digest to.
Email Digests are a great way for top managers to keep track of the big numbers like “Sales Booked” or “Amount Collected” or “Invoices Raised” etc.

View File

@ -18,4 +18,4 @@ This will also set the default **Currency** and time zone for your account. Once
Congrats! You are already on your way.
The next step is to configure your Chart of Accounts or start adding users and setting their permissions.
The next step is to follow implementation instructions.

View File

@ -11,7 +11,7 @@ For Tax Accounts that you want to use in the tax templates, you must mention the
## Sales Taxes and Charges Master
You must usually collect taxes from your Customer and pay them to the government. At times there may be multiple taxes for multiple government bodies like local government, state or provincial and federal or central government.
You must usually collect taxes from your Customer and pay them to the government. At times, you may have to pay multiple taxes to multiple government bodies like local government, state or provincial and federal or central government.
The way ERPNext sets up taxes is via templates. Other types of charges that may apply to your invoices (like shipping, insurance etc.) can also be configured as taxes.
@ -36,9 +36,9 @@ In each row, you have to mention:
- Amount: Tax amount.
- Total: Cumulative total to this point.
- Enter Row: If based on "Previous Row Total" you can select the row number which will be taken as a base for this calculation (default is the previous row).
- Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to your customers.
- Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the rate in your main item table. This is useful when you want to give a flat price (inclusive of all taxes) to your customers.
Once your setup your template, you can now select this in your sales transactions.
Once you setup your template, you can select this in your sales transactions.
## Purchase Taxes and Charges Master

View File

@ -5,11 +5,13 @@
---
### How are Items Valued?
One of the major features of any inventory system is that you can find out the value of any item based on its historic or average price. You can also find the value of all your items for your balance sheet. Why is valuation important?
One of the major features of any inventory system is that you can find out the value of any item based on its historic or average price. You can also find the value of all your items for your balance sheet.
- The buying price fluctuates.
- The value changes because of some process (value add).
- The value changes because of decay, loss etc.
Valuation is important because:
- The buying price may fluctuate.
- The value may change because of some process (value add).
- The value may change because of decay, loss etc.
You may encounter these terms, so lets clarify:
@ -18,7 +20,7 @@ You may encounter these terms, so lets clarify:
There are two major ways in which ERPNext values your items.
- **FIFO (First In First Out):** In this system, ERPNext assumes that you will consume / sell those Items first that you bought first. For example, if you buy an Item at price X and then after a few days at price Y. Thus when you sell your Item, ERPNext will reduce the quantity of the Item priced at X first and then Y.
- **FIFO (First In First Out):** In this system, ERPNext assumes that you will consume / sell those Items first which you bought first. For example, if you buy an Item at price X and then after a few days at price Y, whenever you sell your Item, ERPNext will reduce the quantity of the Item priced at X first and then Y.
![FIFO](img/fifo.png)

View File

@ -13,4 +13,4 @@ Comments are a great way to add information about a transaction that is not a pa
### Tags
Like Assignments and Comments, you can also add your own tags to each type of transactions. These tags can help you search a document and also classify it. ERPNext will also show you all the important tags in in the document list.
Like Assignments and Comments, you can also add your own tags to each type of transactions. These tags can help you search a document and also classify it. ERPNext will also show you all the important tags in the document list.

View File

@ -9,6 +9,6 @@
]
}
---
We live in an era when people are very comfortable communicating, discussing, asking, assigning work and getting feedback electronically. The internet acts a great medium to collaborate on work too. Taking this concept into ERP system, we have designed a bunch of tools whereby you can Assign transactions, manage your To Dos, share and maintain a Calendar, maintain a company wise Knowledge Base, Tag and Comment on transactions and send your Orders, Invoices etc via Email. You can also send instant messages to other users using the Messaging tool.
We live in an era when people are very comfortable communicating, discussing, asking, assigning work and getting feedback electronically. The Internet acts as a great medium to collaborate on work too. Taking this concept into ERP system, we have designed a bunch of tools whereby you can Assign transactions, manage your To Dos, share and maintain a Calendar, maintain a company wise Knowledge Base, Tag and Comment on transactions and send your Orders, Invoices etc via Email. You can also send instant messages to other users using the Messaging tool.
These tools are integrated into all aspects of the product so that you can effectively manage your data and collaborate with your co-workers.

View File

@ -14,7 +14,7 @@ Step 2: Add the User and other details
This transaction will appear in:
The To-do list of the user whom this is assigned to in “My List” section
In the “Assigned by me” section of the user who as assigned this activity.
In the “Assigned by me” section of the user who has assigned this activity.
### To Do

View File

@ -5,7 +5,7 @@
---
Blogs are a great way to share your thoughts about your business and keep your customers and readers updated of what you are up to.
In the age of internet, writing assumes a lot more importance is because when people come to your website, they want to be read about your product and you.
In the age of internet, writing assumes a lot of significance because when people come to your website, they want to read about you and your product.
To create a new blog, just create a new Blog from:

View File

@ -17,9 +17,9 @@ Websites are a core component of any business and having a good website usually
Unless you are a web designer yourself.
Would not it be nice if there was a way to update your product catalog on your site automatically from your ERP?
Wouldn't it be nice if there was a way to update your product catalog on your site automatically from your ERP?
We thought exactly the same and hence built a small Website Development app right inside or ERPNext! Using ERPNexts Website module, you can
We thought exactly the same and hence built a small Website Development app right inside ERPNext! Using ERPNexts Website module, you can
1. Create Web Pages
1. Write a Blog

View File

@ -21,4 +21,4 @@ The web link to your page will be the value of the “Page Name” field + “.h
#### Images
You can attach images to your web page and show them using the <img> HTML tag or using markdown format. the link for your file will be files/filename
You can attach images to your web page and show them using the <img> HTML tag or using markdown format. the link to your file will be files/filename

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:13",
"docstatus": 0,
"modified": "2013-07-10 17:39:22",
"modified": "2013-08-08 14:22:10",
"modified_by": "Administrator",
"owner": "ashwini@webnotestech.com"
},
@ -54,7 +54,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Naming Series",
"label": "Document Numbering Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",

View File

@ -45,6 +45,7 @@ class DocType:
if self.doc.user_id:
self.update_user_default()
self.update_profile()
self.update_dob_event()
def update_user_default(self):
webnotes.conn.set_default("employee", self.doc.name, self.doc.user_id)
@ -154,6 +155,38 @@ class DocType:
msgprint(_("Invalid Leave Approver") + ": \"" + l.leave_approver + "\"",
raise_exception=InvalidLeaveApproverError)
def update_dob_event(self):
if self.doc.status == "Active" and self.doc.date_of_birth:
birthday_event = webnotes.conn.sql("""select name from `tabEvent` where repeat_on='Every Year'
and ref_type='Employee' and ref_name=%s""", self.doc.name)
starts_on = self.doc.date_of_birth + " 00:00:00"
ends_on = self.doc.date_of_birth + " 00:15:00"
if birthday_event:
event = webnotes.bean("Event", birthday_event[0][0])
event.doc.starts_on = starts_on
event.doc.ends_on = ends_on
event.save()
else:
webnotes.bean({
"doctype": "Event",
"subject": _("Birthday") + ": " + self.doc.employee_name,
"description": _("Happy Birthday!") + " " + self.doc.employee_name,
"starts_on": starts_on,
"ends_on": ends_on,
"event_type": "Public",
"all_day": 1,
"send_reminder": 1,
"repeat_this_event": 1,
"repeat_on": "Every Year",
"ref_type": "Employee",
"ref_name": self.doc.name
}).insert()
else:
webnotes.conn.sql("""delete from `tabEvent` where repeat_on='Every Year' and
ref_type='Employee' and ref_name=%s""", self.doc.name)
@webnotes.whitelist()
def get_retirement_date(date_of_birth=None):
import datetime

View File

@ -2,7 +2,7 @@
{
"creation": "2013-03-07 09:04:18",
"docstatus": 0,
"modified": "2013-07-10 12:52:17",
"modified": "2013-08-08 14:22:11",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -76,7 +76,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Naming Series",
"label": "Document Numbering Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",

View File

@ -25,9 +25,11 @@ erpnext.hr.ExpenseClaimController = wn.ui.form.Controller.extend({
// credit to bank
var d1 = wn.model.add_child(jv, 'Journal Voucher Detail', 'entries');
d1.account = r.message[0].account;
d1.credit = cur_frm.doc.total_sanctioned_amount;
d1.balance = r.message[0].balance;
if(r.message) {
d1.account = r.message[0].account;
d1.balance = r.message[0].balance;
}
loaddoc('Journal Voucher', jv.name);
}

View File

@ -115,7 +115,8 @@ class DocType(DocListController):
self.doc.leave_balance = get_leave_balance(self.doc.employee,
self.doc.leave_type, self.doc.fiscal_year)["leave_balance"]
if self.doc.leave_balance - self.doc.total_leave_days < 0:
if self.doc.status != "Rejected" \
and self.doc.leave_balance - self.doc.total_leave_days < 0:
#check if this leave type allow the remaining balance to be in negative. If yes then warn the user and continue to save else warn the user and don't save.
msgprint("There is not enough leave balance for Leave Type: %s" % \
(self.doc.leave_type,),

View File

@ -59,7 +59,7 @@ def validate_install():
return is_redhat, is_debian
def install_using_yum():
packages = "python python-setuptools MySQL-python httpd git memcached ntp vim-enhanced screen"
packages = "python python-setuptools gcc python-devel MySQL-python httpd git memcached ntp vim-enhanced screen"
print "-"*80
print "Installing Packages: (This may take some time)"
@ -108,7 +108,7 @@ def update_config_for_redhat():
def install_using_apt():
exec_in_shell("apt-get update")
packages = "python python-setuptools python-mysqldb apache2 git memcached ntp vim screen htop"
packages = "python python-setuptools python-dev build-essential python-pip python-mysqldb apache2 git memcached ntp vim screen htop"
print "-"*80
print "Installing Packages: (This may take some time)"
print packages
@ -145,7 +145,11 @@ def install_python_modules():
print python_modules
print "-"*80
exec_in_shell("easy_install pip")
if not exec_in_shell("which pip"):
exec_in_shell("easy_install pip")
exec_in_shell("pip install --upgrade pip")
exec_in_shell("pip install --upgrade virtualenv")
exec_in_shell("pip install -q %s" % python_modules)
def install_erpnext(install_path):
@ -309,6 +313,8 @@ def post_install(install_path):
print
print "-"*80
print "To change url domain, run: lib/wnf.py --domain example.com"
print "-"*80
print "Installation complete"
print "Open your browser and go to http://localhost:8080"
print "Login using username = Administrator and password = admin"

View File

@ -118,6 +118,11 @@ class DocType:
rate = self.get_valuation_rate(arg)
elif self.doc.rm_cost_as_per == 'Last Purchase Rate':
rate = arg['last_purchase_rate']
elif self.doc.rm_cost_as_per == "Price List":
if not self.doc.buying_price_list:
webnotes.throw(_("Please select Price List"))
rate = webnotes.conn.get_value("Item Price", {"price_list": self.doc.buying_price_list,
"parent": arg["item_code"]}, "ref_rate") or 0
elif self.doc.rm_cost_as_per == 'Standard Rate':
rate = arg['standard_rate']
@ -180,7 +185,7 @@ class DocType:
webnotes.conn.set(self.doc, "is_default", 0)
sql("update `tabItem` set default_bom = null where name = %s and default_bom = %s",
(self.doc.item, self.doc.name))
(self.doc.item, self.doc.name))
def clear_operations(self):
if not self.doc.with_operations:
@ -250,7 +255,7 @@ class DocType:
(bom_no, item), as_dict =1)
if not bom:
msgprint("""Incorrect BOM No: %s against item: %s at row no: %s.
It may be inactive or cancelled or for some other item.""" %
It may be inactive or not submitted or does not belong to this item.""" %
(bom_no, item, idx), raise_exception = 1)
def check_if_item_repeated(self, item, op, check_list):

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-22 15:11:38",
"docstatus": 0,
"modified": "2013-07-22 15:28:38",
"modified": "2013-08-09 14:47:25",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -66,11 +66,6 @@
"reqd": 1,
"search_index": 1
},
{
"doctype": "DocField",
"fieldname": "cb0",
"fieldtype": "Column Break"
},
{
"allow_on_submit": 1,
"default": "1",
@ -87,6 +82,7 @@
},
{
"allow_on_submit": 1,
"default": "1",
"doctype": "DocField",
"fieldname": "is_default",
"fieldtype": "Check",
@ -96,6 +92,11 @@
"oldfieldname": "is_default",
"oldfieldtype": "Check"
},
{
"doctype": "DocField",
"fieldname": "cb0",
"fieldtype": "Column Break"
},
{
"description": "Manage cost of operations",
"doctype": "DocField",
@ -103,6 +104,22 @@
"fieldtype": "Check",
"label": "With Operations"
},
{
"doctype": "DocField",
"fieldname": "rm_cost_as_per",
"fieldtype": "Select",
"label": "Rate Of Materials Based On",
"options": "Valuation Rate\nLast Purchase Rate\nPrice List"
},
{
"depends_on": "eval:doc.rm_cost_as_per===\"Price List\"",
"description": "Price List for Costing",
"doctype": "DocField",
"fieldname": "buying_price_list",
"fieldtype": "Link",
"label": "Price List",
"options": "Price List"
},
{
"depends_on": "with_operations",
"doctype": "DocField",
@ -145,13 +162,6 @@
"label": "Costing",
"oldfieldtype": "Section Break"
},
{
"doctype": "DocField",
"fieldname": "rm_cost_as_per",
"fieldtype": "Select",
"label": "Rate Of Materials Based On",
"options": "Valuation Rate\nLast Purchase Rate"
},
{
"doctype": "DocField",
"fieldname": "total_cost",

View File

@ -61,30 +61,25 @@ cur_frm.cscript['Unstop Production Order'] = function() {
}
cur_frm.cscript['Transfer Raw Materials'] = function() {
var doc = cur_frm.doc;
cur_frm.cscript.make_se(doc, 'Material Transfer');
cur_frm.cscript.make_se('Material Transfer');
}
cur_frm.cscript['Update Finished Goods'] = function() {
var doc = cur_frm.doc;
cur_frm.cscript.make_se(doc, 'Manufacture/Repack');
cur_frm.cscript.make_se('Manufacture/Repack');
}
cur_frm.cscript.make_se = function(doc, purpose) {
var se = wn.model.get_new_doc("Stock Entry");
se.purpose = purpose;
se.production_order = doc.name;
if(purpose==="Material Transfer") {
se.to_warehouse = doc.wip_warehouse;
} else {
se.from_warehouse = doc.wip_warehouse;
se.to_warehouse = doc.fg_warehouse;
}
se.company = doc.company;
se.fg_completed_qty = doc.qty - doc.produced_qty;
se.bom_no = doc.bom_no;
se.use_multi_level_bom = doc.use_multi_level_bom;
loaddoc('Stock Entry', se.name);
cur_frm.cscript.make_se = function(purpose) {
wn.call({
method:"manufacturing.doctype.production_order.production_order.make_stock_entry",
args: {
"production_order_id": cur_frm.doc.name,
"purpose": purpose
},
callback: function(r) {
var doclist = wn.model.sync(r.message);
wn.set_route("Form", doclist[0].doctype, doclist[0].name);
}
})
}
cur_frm.fields_dict['production_item'].get_query = function(doc) {

View File

@ -10,6 +10,8 @@ from webnotes import msgprint, _
sql = webnotes.conn.sql
class OverProductionError(webnotes.ValidationError): pass
class DocType:
def __init__(self, doc, doclist=[]):
self.doc = doc
@ -71,8 +73,7 @@ class DocType:
cstr(self.doc.production_item) + _(" against sales order") + ": " +
cstr(self.doc.sales_order) + _(" will be ") + cstr(total_qty) + ", " +
_("which is greater than sales order qty ") + "(" + cstr(so_qty) + ")" +
_("Please reduce qty."), raise_exception=1)
_("Please reduce qty."), raise_exception=OverProductionError)
def stop_unstop(self, status):
""" Called from client side on Stop/Unstop event"""
@ -95,6 +96,8 @@ class DocType:
def on_submit(self):
if not self.doc.wip_warehouse:
webnotes.throw(_("WIP Warehouse required before Submit"))
webnotes.conn.set(self.doc,'status', 'Submitted')
self.update_planned_qty(self.doc.qty)
@ -134,4 +137,24 @@ def get_item_details(item):
if bom:
res.bom_no = bom[0][0]
return res
return res
@webnotes.whitelist()
def make_stock_entry(production_order_id, purpose):
production_order = webnotes.bean("Production Order", production_order_id)
stock_entry = webnotes.new_bean("Stock Entry")
stock_entry.doc.purpose = purpose
stock_entry.doc.production_order = production_order_id
stock_entry.doc.company = production_order.doc.company
stock_entry.doc.bom_no = production_order.doc.bom_no
stock_entry.doc.use_multi_level_bom = production_order.doc.use_multi_level_bom
stock_entry.doc.fg_completed_qty = flt(production_order.doc.qty) - flt(production_order.doc.produced_qty)
if purpose=="Material Transfer":
stock_entry.doc.to_warehouse = production_order.doc.wip_warehouse
else:
stock_entry.doc.from_warehouse = production_order.doc.wip_warehouse
stock_entry.doc.to_warehouse = production_order.doc.fg_warehouse
return [d.fields for d in stock_entry.doclist]

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:16",
"docstatus": 0,
"modified": "2013-07-25 16:38:37",
"modified": "2013-08-08 14:22:12",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -55,7 +55,7 @@
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"label": "Document Numbering Series",
"options": "\nPRO",
"reqd": 1
},
@ -152,7 +152,7 @@
"label": "For Warehouse",
"options": "Warehouse",
"read_only": 0,
"reqd": 1
"reqd": 0
},
{
"doctype": "DocField",
@ -165,7 +165,7 @@
"fieldtype": "Link",
"label": "Work-in-Progress Warehouse",
"options": "Warehouse",
"reqd": 1
"reqd": 0
},
{
"doctype": "DocField",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-02-22 01:27:49",
"docstatus": 0,
"modified": "2013-07-25 16:35:27",
"modified": "2013-08-08 12:12:27",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -52,7 +52,6 @@
"width": "100px"
},
{
"default": "0.00",
"doctype": "DocField",
"fieldname": "planned_qty",
"fieldtype": "Float",
@ -76,7 +75,6 @@
"read_only": 1
},
{
"default": "0.00",
"doctype": "DocField",
"fieldname": "so_pending_qty",
"fieldtype": "Float",
@ -89,6 +87,15 @@
"reqd": 0,
"width": "100px"
},
{
"description": "Reserved Warehouse in Sales Order / Finished Goods Warehouse",
"doctype": "DocField",
"fieldname": "warehouse",
"fieldtype": "Link",
"label": "Warehouse",
"options": "Warehouse",
"reqd": 0
},
{
"doctype": "DocField",
"fieldname": "stock_uom",

View File

@ -2,8 +2,8 @@
// License: GNU General Public License v3. See license.txt
cur_frm.cscript.onload = function(doc, cdt, cdn) {
doc.company = wn.defaults.get_default("company");
refresh_field("company");
cur_frm.set_value("company", wn.defaults.get_default("company"))
cur_frm.set_value("use_multi_level_bom", 1)
}
cur_frm.cscript.refresh = function(doc) {

View File

@ -7,7 +7,7 @@ from webnotes.utils import cstr, flt, cint, nowdate, add_days
from webnotes.model.doc import addchild, Document
from webnotes.model.bean import getlist
from webnotes.model.code import get_obj
from webnotes import msgprint
from webnotes import msgprint, _
sql = webnotes.conn.sql
@ -70,12 +70,12 @@ class DocType:
and so.docstatus = 1 and so.status != "Stopped"
and so.company = %s
and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0) %s
and (exists (select * from `tabItem` item where item.name=so_item.item_code
and (exists (select name from `tabItem` item where item.name=so_item.item_code
and (ifnull(item.is_pro_applicable, 'No') = 'Yes'
or ifnull(item.is_sub_contracted_item, 'No') = 'Yes') %s)
or exists (select * from `tabDelivery Note Packing Item` dnpi
or exists (select name from `tabDelivery Note Packing Item` dnpi
where dnpi.parent = so.name and dnpi.parent_item = so_item.item_code
and exists (select * from `tabItem` item where item.name=dnpi.item_code
and exists (select name from `tabItem` item where item.name=dnpi.item_code
and (ifnull(item.is_pro_applicable, 'No') = 'Yes'
or ifnull(item.is_sub_contracted_item, 'No') = 'Yes') %s)))
""" % ('%s', so_filter, item_filter, item_filter), self.doc.company, as_dict=1)
@ -105,9 +105,10 @@ class DocType:
def get_items(self):
so_list = filter(None, [d.sales_order for d in getlist(self.doclist, 'pp_so_details')])
if not so_list:
msgprint("Please enter sales order in the above table", raise_exception=1)
msgprint("Please enter sales order in the above table")
return []
items = sql("""select distinct parent, item_code,
items = sql("""select distinct parent, item_code, reserved_warehouse,
(qty - ifnull(delivered_qty, 0)) as pending_qty
from `tabSales Order Item` so_item
where parent in (%s) and docstatus = 1 and ifnull(qty, 0) > ifnull(delivered_qty, 0)
@ -116,7 +117,7 @@ class DocType:
or ifnull(item.is_sub_contracted_item, 'No') = 'Yes'))""" % \
(", ".join(["%s"] * len(so_list))), tuple(so_list), as_dict=1)
dnpi_items = sql("""select distinct dnpi.parent, dnpi.item_code,
dnpi_items = sql("""select distinct dnpi.parent, dnpi.item_code, dnpi.warehouse as reserved_warhouse,
(((so_item.qty - ifnull(so_item.delivered_qty, 0)) * dnpi.qty) / so_item.qty)
as pending_qty
from `tabSales Order Item` so_item, `tabDelivery Note Packing Item` dnpi
@ -139,6 +140,7 @@ class DocType:
from tabItem where name=%s""", p['item_code'])
pi = addchild(self.doc, 'pp_details', 'Production Plan Item', self.doclist)
pi.sales_order = p['parent']
pi.warehouse = p['reserved_warehouse']
pi.item_code = p['item_code']
pi.description = item_details and item_details[0][0] or ''
pi.stock_uom = item_details and item_details[0][1] or ''
@ -148,6 +150,7 @@ class DocType:
def validate_data(self):
self.validate_company()
for d in getlist(self.doclist, 'pp_details'):
self.validate_bom_no(d)
if not flt(d.planned_qty):
@ -169,7 +172,6 @@ class DocType:
def raise_production_order(self):
"""It will raise production order (Draft) for all distinct FG items"""
self.validate_company()
self.validate_data()
from utilities.transaction_base import validate_uom_is_integer
@ -180,49 +182,54 @@ class DocType:
if pro:
pro = ["""<a href="#Form/Production Order/%s" target="_blank">%s</a>""" % \
(p, p) for p in pro]
msgprint("Following Production Order has been generated:\n" + '\n'.join(pro))
msgprint("Production Order(s) created:\n\n" + '\n'.join(pro))
else :
msgprint("No Production Order generated.")
msgprint("No Production Order created.")
def get_distinct_items_and_boms(self):
""" Club similar BOM and item for processing"""
item_dict, bom_dict = {}, {}
for d in self.doclist.get({"parentfield": "pp_details"}):
for d in self.doclist.get({"parentfield": "pp_details"}):
bom_dict[d.bom_no] = bom_dict.get(d.bom_no, 0) + flt(d.planned_qty)
item_dict[(d.item_code, d.sales_order)] = {
"qty" : flt(item_dict.get((d.item_code, d.sales_order), \
{}).get("qty")) + flt(d.planned_qty),
item_dict[(d.item_code, d.sales_order, d.warehouse)] = {
"production_item" : d.item_code,
"sales_order" : d.sales_order,
"qty" : flt(item_dict.get((d.item_code, d.sales_order, d.warehouse),
{}).get("qty")) + flt(d.planned_qty),
"bom_no" : d.bom_no,
"description" : d.description,
"stock_uom" : d.stock_uom,
"company" : self.doc.company,
"wip_warehouse" : "",
"fg_warehouse" : "",
"fg_warehouse" : d.warehouse,
"status" : "Draft",
}
return bom_dict, item_dict
def create_production_order(self, items):
"""Create production order. Called from Production Planning Tool"""
from manufacturing.doctype.production_order.production_order import OverProductionError
pro_list = []
for item_so in items:
pro_doc = Document('Production Order')
pro_doc.production_item = item_so[0]
pro_doc.sales_order = item_so[1]
for key in items[item_so]:
pro_doc.fields[key] = items[item_so][key]
for key in items:
pro = webnotes.new_bean("Production Order")
pro.doc.fields.update(items[key])
pro_doc.save(new = 1)
get_obj("Production Order", pro_doc.name).validate_production_order_against_so()
pro_list.append(pro_doc.name)
webnotes.mute_messages = True
try:
pro.insert()
pro_list.append(pro.doc.name)
except OverProductionError, e:
pass
webnotes.mute_messages = False
return pro_list
def download_raw_materials(self):
""" Create csv data for required raw material to produce finished goods"""
self.validate_data()
bom_dict = self.get_distinct_items_and_boms()[0]
self.get_raw_materials(bom_dict)
return self.get_csv()
@ -283,12 +290,17 @@ class DocType:
Raise Material Request if projected qty is less than qty required
Requested qty should be shortage qty considering minimum order qty
"""
self.validate_data()
if not self.doc.purchase_request_for_warehouse:
webnotes.msgprint("Please enter Warehouse for which Material Request will be raised",
raise_exception=1)
bom_dict = self.get_distinct_items_and_boms()[0]
bom_dict = self.get_distinct_items_and_boms()[0]
self.get_raw_materials(bom_dict)
if not self.item_dict:
return
item_projected_qty = self.get_projected_qty()
from accounts.utils import get_fiscal_year
@ -355,7 +367,7 @@ class DocType:
if purchase_request_list:
pur_req = ["""<a href="#Form/Material Request/%s" target="_blank">%s</a>""" % \
(p, p) for p in purchase_request_list]
webnotes.msgprint("Following Material Request created successfully: \n%s" %
webnotes.msgprint("Material Request(s) created: \n%s" %
"\n".join(pur_req))
else:
webnotes.msgprint("Nothing to request")

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-21 12:03:47",
"docstatus": 0,
"modified": "2013-07-22 15:26:45",
"modified": "2013-08-08 12:01:02",
"modified_by": "Administrator",
"owner": "jai@webnotestech.com"
},
@ -118,46 +118,17 @@
},
{
"doctype": "DocField",
"fieldname": "clear_so_table",
"fieldtype": "Button",
"label": "Clear Table",
"options": "clear_so_table"
},
{
"description": "Enter items and planned qty for which you want to raise production orders or download raw materials for analysis.",
"doctype": "DocField",
"fieldname": "create_production_orders",
"fieldname": "items_for_production",
"fieldtype": "Section Break",
"label": "Create Production Orders"
"label": "Select Items"
},
{
"description": "Pull items from Sales Order mentioned in the above table.",
"doctype": "DocField",
"fieldname": "get_items_from_so",
"fieldtype": "Button",
"label": "Get Items",
"label": "Get Items From Sales Orders",
"options": "get_items_from_so"
},
{
"doctype": "DocField",
"fieldname": "pp_details",
"fieldtype": "Table",
"label": "Production Plan Items",
"options": "Production Plan Item"
},
{
"doctype": "DocField",
"fieldname": "clear_item_table",
"fieldtype": "Button",
"label": "Clear Table",
"options": "clear_item_table"
},
{
"doctype": "DocField",
"fieldname": "section_break3",
"fieldtype": "Section Break",
"options": "Simple"
},
{
"default": "1",
"description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.",
@ -169,36 +140,31 @@
},
{
"doctype": "DocField",
"fieldname": "cb5",
"fieldtype": "Column Break",
"width": "50%"
"fieldname": "pp_details",
"fieldtype": "Table",
"label": "Production Plan Items",
"options": "Production Plan Item"
},
{
"description": "Enter items and planned qty for which you want to raise production orders or download raw materials for analysis.",
"doctype": "DocField",
"fieldname": "create_production_orders",
"fieldtype": "Section Break",
"label": "Production Orders"
},
{
"description": "Separate production order will be created for each finished good item.",
"doctype": "DocField",
"fieldname": "raise_production_order",
"fieldtype": "Button",
"label": "Raise Production Order",
"label": "Create Production Orders",
"options": "raise_production_order"
},
{
"doctype": "DocField",
"fieldname": "sb5",
"fieldtype": "Section Break",
"label": "Materials Requirement Planning (MRP)"
},
{
"description": "Download a report containing all raw materials with their latest inventory status",
"doctype": "DocField",
"fieldname": "download_materials_required",
"fieldtype": "Button",
"label": "Download Materials Required"
},
{
"doctype": "DocField",
"fieldname": "column_break6",
"fieldtype": "Column Break",
"width": "50%"
"label": "Material Requirement"
},
{
"doctype": "DocField",
@ -212,9 +178,16 @@
"doctype": "DocField",
"fieldname": "raise_purchase_request",
"fieldtype": "Button",
"label": "Raise Material Request",
"label": "Create Material Requests",
"options": "raise_purchase_request"
},
{
"description": "Download a report containing all raw materials with their latest inventory status",
"doctype": "DocField",
"fieldname": "download_materials_required",
"fieldtype": "Button",
"label": "Download Materials Required"
},
{
"doctype": "DocPerm"
}

View File

@ -64,11 +64,26 @@ wn.module_page["Manufacturing"] = [
right: true,
icon: "icon-list",
items: [
{
"label":wn._("Open Production Orders"),
route: "query-report/Open Production Orders",
doctype:"Production Order"
},
{
"label":wn._("Production Orders in Progress"),
route: "query-report/Production Orders in Progress",
doctype:"Production Order"
},
{
"label":wn._("Issued Items Against Production Order"),
route: "query-report/Issued Items Against Production Order",
doctype:"Production Order"
},
{
"label":wn._("Completed Production Orders"),
route: "query-report/Completed Production Orders",
doctype:"Production Order"
},
]
}
]

View File

@ -0,0 +1,22 @@
[
{
"creation": "2013-08-12 12:44:27",
"docstatus": 0,
"modified": "2013-08-12 12:44:27",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"query": "SELECT\n `tabProduction Order`.name as \"Production Order:Link/Production Order:200\",\n `tabProduction Order`.creation as \"Date:Date:120\",\n `tabProduction Order`.production_item as \"Item:Link/Item:150\",\n `tabProduction Order`.qty as \"To Produce:Int:100\",\n `tabProduction Order`.produced_qty as \"Produced:Int:100\"\nFROM\n `tabProduction Order`\nWHERE\n `tabProduction Order`.docstatus=1\n AND ifnull(`tabProduction Order`.produced_qty,0) = `tabProduction Order`.qty",
"ref_doctype": "Production Order",
"report_name": "Completed Production Orders",
"report_type": "Query Report"
},
{
"doctype": "Report",
"name": "Completed Production Orders"
}
]

View File

@ -0,0 +1,22 @@
[
{
"creation": "2013-08-12 12:32:30",
"docstatus": 0,
"modified": "2013-08-12 12:42:29",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"query": "SELECT\n `tabProduction Order`.name as \"Production Order:Link/Production Order:200\",\n `tabProduction Order`.creation as \"Date:Date:120\",\n `tabProduction Order`.production_item as \"Item:Link/Item:150\",\n `tabProduction Order`.qty as \"To Produce:Int:100\",\n `tabProduction Order`.produced_qty as \"Produced:Int:100\"\nFROM\n `tabProduction Order`\nWHERE\n `tabProduction Order`.docstatus=1\n AND ifnull(`tabProduction Order`.produced_qty,0) < `tabProduction Order`.qty\n AND NOT EXISTS (SELECT name from `tabStock Entry` where production_order =`tabProduction Order`.name) ",
"ref_doctype": "Production Order",
"report_name": "Open Production Orders",
"report_type": "Query Report"
},
{
"doctype": "Report",
"name": "Open Production Orders"
}
]

View File

@ -0,0 +1,22 @@
[
{
"creation": "2013-08-12 12:43:47",
"docstatus": 0,
"modified": "2013-08-12 12:43:47",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"query": "SELECT\n `tabProduction Order`.name as \"Production Order:Link/Production Order:200\",\n `tabProduction Order`.creation as \"Date:Date:120\",\n `tabProduction Order`.production_item as \"Item:Link/Item:150\",\n `tabProduction Order`.qty as \"To Produce:Int:100\",\n `tabProduction Order`.produced_qty as \"Produced:Int:100\"\nFROM\n `tabProduction Order`\nWHERE\n `tabProduction Order`.docstatus=1\n AND ifnull(`tabProduction Order`.produced_qty,0) < `tabProduction Order`.qty\n AND EXISTS (SELECT name from `tabStock Entry` where production_order =`tabProduction Order`.name) ",
"ref_doctype": "Production Order",
"report_name": "Production Orders in Progress",
"report_type": "Query Report"
},
{
"doctype": "Report",
"name": "Production Orders in Progress"
}
]

Some files were not shown because too many files have changed in this diff Show More