Merge branch 'responsive' of github.com:webnotes/erpnext into responsive

Conflicts:
	stock/doctype/material_request/material_request.txt
This commit is contained in:
Anand Doshi
2013-07-08 18:54:00 +05:30
34 changed files with 379 additions and 1345 deletions

View File

@@ -53,6 +53,25 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
}
cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms);
}
if (this.frm.doc.docstatus===0) {
cur_frm.add_custom_button(wn._('From Opportunity'),
function() {
wn.model.map_current_doc({
method: "selling.doctype.opportunity.opportunity.make_quotation",
source_doctype: "Opportunity",
get_query_filters: {
docstatus: 1,
status: "Submitted",
enquiry_type: cur_frm.doc.order_type,
customer: cur_frm.doc.customer || undefined,
lead: cur_frm.doc.lead || undefined,
company: cur_frm.doc.company
}
})
});
}
if (!doc.__islocal) {
cur_frm.communication_view = new wn.views.CommunicationList({
@@ -70,6 +89,10 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
this.frm.toggle_reqd("lead", this.frm.doc.quotation_to == "Lead");
this.frm.toggle_reqd("customer", this.frm.doc.quotation_to == "Customer");
},
tc_name: function() {
this.get_terms();
},
validate_company_and_party: function(party_field) {
if(this.frm.doc.quotation_to == "Lead") {
@@ -113,17 +136,6 @@ cur_frm.cscript.lead = function(doc, cdt, cdn) {
}
// =====================================================================================
cur_frm.fields_dict['enq_no'].get_query = function(doc,cdt,cdn){
var cond='';
var cond1='';
if(doc.order_type) cond = 'ifnull(`tabOpportunity`.enquiry_type, "") = "'+doc.order_type+'" AND';
if(doc.customer) cond1 = '`tabOpportunity`.customer = "'+doc.customer+'" AND';
else if(doc.lead) cond1 = '`tabOpportunity`.lead = "'+doc.lead+'" AND';
return repl('SELECT `tabOpportunity`.`name` FROM `tabOpportunity` WHERE `tabOpportunity`.`docstatus` = 1 AND `tabOpportunity`.status = "Submitted" AND %(cond)s %(cond1)s `tabOpportunity`.`name` LIKE "%s" ORDER BY `tabOpportunity`.`name` ASC LIMIT 50', {cond:cond, cond1:cond1});
}
// Make Sales Order
// =====================================================================================
cur_frm.cscript['Make Sales Order'] = function() {
@@ -133,14 +145,6 @@ cur_frm.cscript['Make Sales Order'] = function() {
})
}
//pull enquiry details
cur_frm.cscript.pull_enquiry_detail = function(doc,cdt,cdn){
wn.model.map_current_doc({
method: "selling.doctype.opportunity.opportunity.make_quotation",
source_name: cur_frm.doc.enq_no,
})
}
// declare order lost
//-------------------------
cur_frm.cscript['Declare Order Lost'] = function(){

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-05-24 19:29:08",
"docstatus": 0,
"modified": "2013-07-05 14:52:37",
"modified": "2013-07-08 15:51:41",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -344,42 +344,6 @@
"fieldtype": "Section Break",
"read_only": 0
},
{
"description": "To create Quotation against Opportunity, Select Opportunity No. and click on 'Pull Opportunity Details' ",
"doctype": "DocField",
"fieldname": "enq_no",
"fieldtype": "Link",
"hidden": 0,
"in_filter": 1,
"label": "Opportunity No",
"no_copy": 0,
"oldfieldname": "enq_no",
"oldfieldtype": "Link",
"options": "Opportunity",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"search_index": 0
},
{
"doctype": "DocField",
"fieldname": "pull_enquiry_detail",
"fieldtype": "Button",
"hidden": 0,
"label": "Pull Opportunity Detail",
"no_copy": 0,
"oldfieldtype": "Button",
"print_hide": 0,
"read_only": 0,
"report_hide": 0
},
{
"doctype": "DocField",
"fieldname": "col_break34",
"fieldtype": "Column Break",
"read_only": 0,
"width": "50%"
},
{
"doctype": "DocField",
"fieldname": "net_total_export",
@@ -634,24 +598,6 @@
"read_only": 0,
"report_hide": 1
},
{
"doctype": "DocField",
"fieldname": "column_break_54",
"fieldtype": "Column Break"
},
{
"doctype": "DocField",
"fieldname": "get_terms",
"fieldtype": "Button",
"label": "Get Terms and Conditions",
"oldfieldtype": "Button",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "section_break_56",
"fieldtype": "Section Break"
},
{
"doctype": "DocField",
"fieldname": "terms",

View File

@@ -325,21 +325,18 @@ class DocType(TransactionBase):
if so_status == 'Stopped':
msgprint("You cannot do any transaction against Sales Order : '%s' as it is Stopped." %(ref_doc_name))
raise Exception
# ****** Check for Item.is_sales_item = 'Yes' and Item.docstatus != 2 *******
def check_active_sales_items(self,obj):
for d in getlist(obj.doclist, obj.fname):
if d.item_code: # extra condn coz item_code is not mandatory in RV
valid_item = webnotes.conn.sql("select docstatus,is_sales_item, is_service_item from tabItem where name = %s",d.item_code)
if valid_item and valid_item[0][0] == 2:
msgprint("Item : '%s' does not exist in system." %(d.item_code))
raise Exception
sales_item = valid_item and valid_item[0][1] or 'No'
service_item = valid_item and valid_item[0][2] or 'No'
if sales_item == 'No' and service_item == 'No':
msgprint("Item : '%s' is neither Sales nor Service Item"%(d.item_code))
if d.item_code:
item = webnotes.conn.sql("""select docstatus, is_sales_item,
is_service_item, default_income_account from tabItem where name = %s""",
d.item_code, as_dict=True)[0]
if item.is_sales_item == 'No' and item.is_service_item == 'No':
msgprint("Item : '%s' is neither Sales nor Service Item" % (d.item_code))
raise Exception
if d.income_account and not item.default_income_account:
webnotes.conn.set_value("Item", d.item_code, "default_income_account", d.income_account)
# **************************************************************************************************************************************************
@@ -368,291 +365,3 @@ class DocType(TransactionBase):
dt = webnotes.conn.sql("select transaction_date from `tab%s` where name = '%s'" % (d.prevdoc_doctype, d.prevdoc_docname))
d.prevdoc_date = (dt and dt[0][0]) and dt[0][0].strftime('%Y-%m-%d') or ''
def update_prevdoc_detail(self, is_submit, obj):
StatusUpdater(obj, is_submit).update()
#
# make item code readonly if (detail no is set)
#
class StatusUpdater:
"""
Updates the status of the calling records
From Delivery Note
- Update Delivered Qty
- Update Percent
- Validate over delivery
From Sales Invoice
- Update Billed Amt
- Update Percent
- Validate over billing
From Installation Note
- Update Installed Qty
- Update Percent Qty
- Validate over installation
"""
def __init__(self, obj, is_submit):
self.obj = obj # caller object
self.is_submit = is_submit
self.tolerance = {}
self.global_tolerance = None
def update(self):
self.update_all_qty()
self.validate_all_qty()
def validate_all_qty(self):
"""
Validates over-billing / delivery / installation in Delivery Note, Sales Invoice, Installation Note
To called after update_all_qty
"""
if self.obj.doc.doctype=='Delivery Note':
self.validate_qty({
'source_dt' :'Delivery Note Item',
'compare_field' :'delivered_qty',
'compare_ref_field' :'qty',
'target_dt' :'Sales Order Item',
'join_field' :'prevdoc_detail_docname'
})
elif self.obj.doc.doctype=='Sales Invoice':
self.validate_qty({
'source_dt' :'Sales Invoice Item',
'compare_field' :'billed_amt',
'compare_ref_field' :'export_amount',
'target_dt' :'Sales Order Item',
'join_field' :'so_detail'
})
self.validate_qty({
'source_dt' :'Sales Invoice Item',
'compare_field' :'billed_amt',
'compare_ref_field' :'export_amount',
'target_dt' :'Delivery Note Item',
'join_field' :'dn_detail'
}, no_tolerance =1)
elif self.obj.doc.doctype=='Installation Note':
self.validate_qty({
'source_dt' :'Installation Item Details',
'compare_field' :'installed_qty',
'compare_ref_field' :'qty',
'target_dt' :'Delivery Note Item',
'join_field' :'dn_detail'
}, no_tolerance =1)
def get_tolerance_for(self, item_code):
"""
Returns the tolerance for the item, if not set, returns global tolerance
"""
if self.tolerance.get(item_code):
return self.tolerance[item_code]
tolerance = flt(webnotes.conn.get_value('Item',item_code,'tolerance') or 0)
if not tolerance:
if self.global_tolerance == None:
self.global_tolerance = flt(webnotes.conn.get_value('Stock Settings',None,'tolerance') or 0)
tolerance = self.global_tolerance
self.tolerance[item_code] = tolerance
return tolerance
def check_overflow_with_tolerance(self, item, args):
"""
Checks if there is overflow condering a relaxation tolerance
"""
# check if overflow is within tolerance
tolerance = self.get_tolerance_for(item['item_code'])
overflow_percent = ((item[args['compare_field']] - item[args['compare_ref_field']]) / item[args['compare_ref_field']]) * 100
if overflow_percent - tolerance > 0.01:
item['max_allowed'] = flt(item[args['compare_ref_field']] * (100+tolerance)/100)
item['reduce_by'] = item[args['compare_field']] - item['max_allowed']
msgprint("""
Row #%(idx)s: Max %(compare_ref_field)s allowed for <b>Item %(item_code)s</b> against <b>%(parenttype)s %(parent)s</b> is <b>%(max_allowed)s</b>.
If you want to increase your overflow tolerance, please increase tolerance %% in Global Defaults or Item master.
Or, you must reduce the %(compare_ref_field)s by %(reduce_by)s
Also, please check if the order item has already been billed in the Sales Order""" % item, raise_exception=1)
def validate_qty(self, args, no_tolerance=None):
"""
Validates qty at row level
"""
# get unique transactions to update
for d in self.obj.doclist:
if d.doctype == args['source_dt'] and d.fields.get(args["join_field"]):
args['name'] = d.fields[args['join_field']]
# get all qty where qty > compare_field
item = webnotes.conn.sql("""select item_code, `%(compare_ref_field)s`,
`%(compare_field)s`, parenttype, parent from `tab%(target_dt)s`
where `%(compare_ref_field)s` < `%(compare_field)s`
and name="%(name)s" and docstatus=1
""" % args, as_dict=1)
if item:
item = item[0]
item['idx'] = d.idx
item['compare_ref_field'] = args['compare_ref_field'].replace('_', ' ')
if not item[args['compare_ref_field']]:
msgprint("As %(compare_ref_field)s for item: %(item_code)s in %(parenttype)s: %(parent)s is zero, system will not check over-delivery or over-billed" % item)
elif no_tolerance:
item['reduce_by'] = item[args['compare_field']] - item[args['compare_ref_field']]
if item['reduce_by'] > .01:
msgprint("""
Row #%(idx)s: Max %(compare_ref_field)s allowed for <b>Item %(item_code)s</b> against
<b>%(parenttype)s %(parent)s</b> is <b>""" % item
+ cstr(item[args['compare_ref_field']]) + """</b>.
You must reduce the %(compare_ref_field)s by %(reduce_by)s""" % item, raise_exception=1)
else:
self.check_overflow_with_tolerance(item, args)
def update_all_qty(self):
"""
Updates delivered / billed / installed qty in Sales Order & Delivery Note
"""
if self.obj.doc.doctype=='Delivery Note':
self.update_qty({
'target_field' :'delivered_qty',
'target_dt' :'Sales Order Item',
'target_parent_dt' :'Sales Order',
'target_parent_field' :'per_delivered',
'target_ref_field' :'qty',
'source_dt' :'Delivery Note Item',
'source_field' :'qty',
'join_field' :'prevdoc_detail_docname',
'percent_join_field' :'prevdoc_docname',
'status_field' :'delivery_status',
'keyword' :'Delivered'
})
elif self.obj.doc.doctype=='Sales Invoice':
self.update_qty({
'target_field' :'billed_amt',
'target_dt' :'Sales Order Item',
'target_parent_dt' :'Sales Order',
'target_parent_field' :'per_billed',
'target_ref_field' :'export_amount',
'source_dt' :'Sales Invoice Item',
'source_field' :'export_amount',
'join_field' :'so_detail',
'percent_join_field' :'sales_order',
'status_field' :'billing_status',
'keyword' :'Billed'
})
self.update_qty({
'target_field' :'billed_amt',
'target_dt' :'Delivery Note Item',
'target_parent_dt' :'Delivery Note',
'target_parent_field' :'per_billed',
'target_ref_field' :'export_amount',
'source_dt' :'Sales Invoice Item',
'source_field' :'export_amount',
'join_field' :'dn_detail',
'percent_join_field' :'delivery_note',
'status_field' :'billing_status',
'keyword' :'Billed'
})
if cint(self.obj.doc.is_pos) == 1:
self.update_qty({
'target_field' :'delivered_qty',
'target_dt' :'Sales Order Item',
'target_parent_dt' :'Sales Order',
'target_parent_field' :'per_delivered',
'target_ref_field' :'qty',
'source_dt' :'Sales Invoice Item',
'source_field' :'qty',
'join_field' :'so_detail',
'percent_join_field' :'sales_order',
'status_field' :'delivery_status',
'keyword' :'Delivered'
})
if self.obj.doc.doctype=='Installation Note':
self.update_qty({
'target_field' :'installed_qty',
'target_dt' :'Delivery Note Item',
'target_parent_dt' :'Delivery Note',
'target_parent_field' :'per_installed',
'target_ref_field' :'qty',
'source_dt' :'Installation Note Item',
'source_field' :'qty',
'join_field' :'prevdoc_detail_docname',
'percent_join_field' :'prevdoc_docname',
'status_field' :'installation_status',
'keyword' :'Installed'
})
def update_qty(self, args):
"""
Updates qty at row level
"""
# condition to include current record (if submit or no if cancel)
if self.is_submit:
args['cond'] = ' or parent="%s"' % self.obj.doc.name
else:
args['cond'] = ' and parent!="%s"' % self.obj.doc.name
# update quantities in child table
for d in self.obj.doclist:
if d.doctype == args['source_dt']:
# updates qty in the child table
args['detail_id'] = d.fields.get(args['join_field'])
if args['detail_id']:
webnotes.conn.sql("""
update
`tab%(target_dt)s`
set
%(target_field)s = (select sum(%(source_field)s) from `tab%(source_dt)s` where `%(join_field)s`="%(detail_id)s" and (docstatus=1 %(cond)s))
where
name="%(detail_id)s"
""" % args)
# get unique transactions to update
for name in set([d.fields.get(args['percent_join_field']) for d in self.obj.doclist if d.doctype == args['source_dt']]):
if name:
args['name'] = name
# update percent complete in the parent table
webnotes.conn.sql("""
update
`tab%(target_parent_dt)s`
set
%(target_parent_field)s =
(select sum(if(%(target_ref_field)s > ifnull(%(target_field)s, 0), %(target_field)s, %(target_ref_field)s))/sum(%(target_ref_field)s)*100 from `tab%(target_dt)s` where parent="%(name)s"),
modified = now()
where
name="%(name)s"
""" % args)
# update field
if args['status_field']:
webnotes.conn.sql("""
update
`tab%(target_parent_dt)s`
set
%(status_field)s = if(ifnull(%(target_parent_field)s,0)<0.001, 'Not %(keyword)s',
if(%(target_parent_field)s>=99.99, 'Fully %(keyword)s', 'Partly %(keyword)s')
)
where
name="%(name)s"
""" % args)

View File

@@ -69,14 +69,35 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
cur_frm.add_custom_button('Unstop', cur_frm.cscript['Unstop Sales Order']);
}
}
if (this.frm.doc.docstatus===0) {
cur_frm.add_custom_button(wn._('From Quotation'),
function() {
wn.model.map_current_doc({
method: "selling.doctype.quotation.quotation.make_sales_order",
source_doctype: "Quotation",
get_query_filters: {
docstatus: 1,
status: ["!=", "Order Lost"],
order_type: cur_frm.doc.order_type,
customer: cur_frm.doc.customer || undefined,
company: cur_frm.doc.company
}
})
});
}
this.order_type(doc);
},
order_type: function() {
this.frm.toggle_reqd("delivery_date", this.frm.doc.order_type == "Sales");
},
tc_name: function() {
this.get_terms();
},
reserved_warehouse: function(doc, cdt, cdn) {
this.warehouse(doc, cdt, cdn);
},
@@ -115,16 +136,6 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
source_name: cur_frm.doc.name
})
},
pull_quotation_details: function() {
wn.model.map_current_doc({
method: "selling.doctype.quotation.quotation.make_sales_order",
source_name: cur_frm.doc.quotation_no,
});
unhide_field(['quotation_date', 'customer_address',
'contact_person', 'territory', 'customer_group']);
}
});
// for backward compatibility: combine new and previous states
@@ -151,22 +162,6 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
ORDER BY `tabProject`.name ASC LIMIT 50', {cond:cond});
}
cur_frm.fields_dict['quotation_no'].get_query = function(doc) {
var cond='';
if(doc.order_type) cond = ' ifnull(`tabQuotation`.order_type, "") = "'
+doc.order_type+'" and';
if(doc.customer) cond += ' ifnull(`tabQuotation`.customer, "") = "'
+doc.customer+'" and';
return repl('SELECT DISTINCT name, customer, transaction_date FROM `tabQuotation` \
WHERE `tabQuotation`.company = "'
+ doc.company + '" and `tabQuotation`.`docstatus` = 1 \
and `tabQuotation`.status != "Order Lost" \
and %(cond)s `tabQuotation`.%(key)s LIKE "%s" \
ORDER BY `tabQuotation`.`name` DESC LIMIT 50', {cond:cond});
}
cur_frm.cscript['Stop Sales Order'] = function() {
var doc = cur_frm.doc;

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-06-18 12:39:59",
"docstatus": 0,
"modified": "2013-07-06 18:38:37",
"modified": "2013-07-08 15:54:25",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -33,8 +33,8 @@
"parent": "Sales Order",
"parentfield": "permissions",
"parenttype": "DocType",
"read": 1,
"report": 1
"permlevel": 0,
"read": 1
},
{
"doctype": "DocType",
@@ -364,55 +364,6 @@
"print_hide": 1,
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "section_break0",
"fieldtype": "Section Break"
},
{
"description": "Quotation no against which this Sales Order is made ",
"doctype": "DocField",
"fieldname": "quotation_no",
"fieldtype": "Link",
"in_filter": 1,
"label": "Quotation No",
"no_copy": 0,
"oldfieldname": "quotation_no",
"oldfieldtype": "Link",
"options": "Quotation",
"print_hide": 1,
"search_index": 1,
"width": "150px"
},
{
"depends_on": "eval:doc.quotation_no",
"doctype": "DocField",
"fieldname": "quotation_date",
"fieldtype": "Date",
"hidden": 1,
"label": "Quotation Date",
"no_copy": 0,
"oldfieldname": "quotation_date",
"oldfieldtype": "Date",
"print_hide": 1,
"read_only": 1,
"reqd": 0,
"width": "100px"
},
{
"doctype": "DocField",
"fieldname": "pull_quotation_details",
"fieldtype": "Button",
"label": "Pull Quotation Items",
"oldfieldtype": "Button",
"print_hide": 1
},
{
"doctype": "DocField",
"fieldname": "col_break20",
"fieldtype": "Column Break",
"width": "50%"
},
{
"doctype": "DocField",
"fieldname": "net_total_export",
@@ -647,24 +598,6 @@
"print_hide": 1,
"search_index": 0
},
{
"doctype": "DocField",
"fieldname": "column_break_58",
"fieldtype": "Column Break"
},
{
"doctype": "DocField",
"fieldname": "get_terms",
"fieldtype": "Button",
"label": "Get Terms and Conditions",
"oldfieldtype": "Button",
"print_hide": 1
},
{
"doctype": "DocField",
"fieldname": "section_break_60",
"fieldtype": "Section Break"
},
{
"doctype": "DocField",
"fieldname": "terms",
@@ -974,23 +907,13 @@
"options": "Sales Team",
"print_hide": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 1,
"role": "Sales Manager",
"submit": 0,
"write": 0
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
"role": "Sales Manager",
"report": 1,
"role": "Sales User",
"submit": 1,
"write": 1
},
@@ -999,63 +922,18 @@
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
"role": "Sales User",
"report": 1,
"role": "Maintenance User",
"submit": 1,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 1,
"role": "Sales User",
"submit": 0,
"write": 0
"role": "Accounts User"
},
{
"doctype": "DocPerm",
"match": "customer_name",
"permlevel": 0,
"match": "customer",
"role": "Customer"
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
"role": "Maintenance Manager",
"submit": 1,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 1,
"role": "Maintenance Manager",
"submit": 0
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
"role": "Maintenance User",
"submit": 1,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 1,
"role": "Maintenance User",
"submit": 0
}
]

View File

@@ -113,8 +113,10 @@ def _get_basic_details(args, item_bean):
"description": item.description_html or item.description,
"reserved_warehouse": item.default_warehouse or args.warehouse or args.reserved_warehouse,
"warehouse": item.default_warehouse or args.warehouse,
"income_account": item.default_income_account or args.income_account,
"expense_account": item.purchase_account or args.expense_account,
"income_account": item.default_income_account or args.income_account \
or webnotes.conn.get_value("Company", args.company, "default_income_account"),
"expense_account": item.purchase_account or args.expense_account \
or webnotes.conn.get_value("Company", args.company, "default_expense_account"),
"cost_center": item.default_sales_cost_center or args.cost_center,
"qty": 1.0,
"adj_rate": 0.0,