[FIX] Forward-port of saas-5 up to 0d330ca

This commit is contained in:
Olivier Dony 2014-06-25 18:57:13 +02:00
commit 668b8c2b2d
4 changed files with 74 additions and 68 deletions

View File

@ -19,9 +19,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from datetime import datetime
from dateutil.relativedelta import relativedelta
import time
from openerp.osv import fields, osv
from openerp.tools.translate import _
@ -55,7 +52,7 @@ class purchase_requisition(osv.osv):
'procurement_id': fields.many2one('procurement.order', 'Procurement', ondelete='set null'),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
'state': fields.selection([('draft', 'Draft'), ('in_progress', 'Confirmed'), ('open', 'Bid Selection'), ('done', 'PO Created'), ('cancel', 'Cancelled')],
'Status', track_visibility='onchange', required=True),
'Status', track_visibility='onchange', required=True),
'multiple_rfq_per_supplier': fields.boolean('Multiple RFQ per supplier'),
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'),
'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', required=True),
@ -63,7 +60,7 @@ class purchase_requisition(osv.osv):
def _get_picking_in(self, cr, uid, context=None):
obj_data = self.pool.get('ir.model.data')
return obj_data.get_object_reference(cr, uid, 'stock','picking_type_in')[1]
return obj_data.get_object_reference(cr, uid, 'stock', 'picking_type_in')[1]
_defaults = {
'state': 'draft',
@ -85,14 +82,11 @@ class purchase_requisition(osv.osv):
def tender_cancel(self, cr, uid, ids, context=None):
purchase_order_obj = self.pool.get('purchase.order')
#try to set all associated quotations to cancel state
purchase_ids = []
# try to set all associated quotations to cancel state
for tender in self.browse(cr, uid, ids, context=context):
for purchase_order in tender.purchase_ids:
purchase_order_obj.action_cancel(cr, uid, [purchase_order.id], context=context)
purchase_order_obj.message_post(cr, uid, [purchase_order.id], body=_('Cancelled by the tender associated to this quotation.'), context=context)
procurement_ids = self.pool['procurement.order'].search(cr, uid, [('requisition_id', 'in', ids)], context=context)
self.pool['procurement.order'].action_done(cr, uid, procurement_ids)
return self.write(cr, uid, ids, {'state': 'cancel'})
def tender_in_progress(self, cr, uid, ids, context=None):
@ -110,8 +104,6 @@ class purchase_requisition(osv.osv):
return True
def tender_done(self, cr, uid, ids, context=None):
procurement_ids = self.pool['procurement.order'].search(cr, uid, [('requisition_id', 'in', ids)], context=context)
self.pool['procurement.order'].action_done(cr, uid, procurement_ids)
return self.write(cr, uid, ids, {'state': 'done'}, context=context)
def open_product_line(self, cr, uid, ids, context=None):
@ -167,8 +159,11 @@ class purchase_requisition(osv.osv):
date_order = requisition.ordering_date or fields.date.context_today(self, cr, uid, context=context)
qty = product_uom._compute_qty(cr, uid, requisition_line.product_uom_id.id, requisition_line.product_qty, default_uom_po_id)
supplier_pricelist = supplier.property_product_pricelist_purchase and supplier.property_product_pricelist_purchase.id or False
vals = po_line_obj.onchange_product_id(cr, uid, [], supplier_pricelist, product.id, qty, default_uom_po_id,
supplier.id, date_order=date_order, fiscal_position_id=supplier.property_account_position, date_planned=requisition_line.schedule_date,
vals = po_line_obj.onchange_product_id(
cr, uid, [], supplier_pricelist, product.id, qty, default_uom_po_id,
supplier.id, date_order=date_order,
fiscal_position_id=supplier.property_account_position,
date_planned=requisition_line.schedule_date,
name=False, price_unit=False, state='draft', context=context)['value']
vals.update({
'order_id': purchase_id,
@ -237,8 +232,6 @@ class purchase_requisition(osv.osv):
"""
Generate all purchase order based on selected lines, should only be called on one tender at a time
"""
if context is None:
contex = {}
po = self.pool.get('purchase.order')
poline = self.pool.get('purchase.order.line')
id_per_supplier = {}
@ -271,8 +264,7 @@ class purchase_requisition(osv.osv):
id_per_supplier[po_line.partner_id.id] = [po_line]
#generate po based on supplier and cancel all previous RFQ
ctx = context.copy()
ctx['force_requisition_id'] = True
ctx = dict(context or {}, force_requisition_id=True)
for supplier, product_line in id_per_supplier.items():
#copy a quotation for this supplier and change order_line then validate it
quotation_id = po.search(cr, uid, [('requisition_id', '=', tender.id), ('partner_id', '=', supplier)], limit=1)[0]
@ -356,10 +348,6 @@ class purchase_order(osv.osv):
proc_obj.write(cr, uid, proc_ids, {'purchase_id': po.id})
self.signal_purchase_cancel(cr, uid, [order.id])
po.requisition_id.tender_done(context=context)
if po.requisition_id and all(purchase_id.state in ['draft', 'cancel'] for purchase_id in po.requisition_id.purchase_ids if purchase_id.id != po.id):
procurement_ids = self.pool['procurement.order'].search(cr, uid, [('requisition_id', '=', po.requisition_id.id)], context=context)
for procurement in proc_obj.browse(cr, uid, procurement_ids, context=context):
procurement.move_id.write({'location_id': procurement.move_id.location_dest_id.id})
return res
def copy(self, cr, uid, id, default=None, context=None):
@ -437,12 +425,9 @@ class procurement_order(osv.osv):
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
def _check(self, cr, uid, procurement, context=None):
requisition_obj = self.pool.get('purchase.requisition')
if procurement.rule_id and procurement.rule_id.action == 'buy' and procurement.product_id.purchase_requisition:
if procurement.requisition_id.state == 'done':
if any([purchase.shipped for purchase in procurement.requisition_id.purchase_ids]):
return True
return False
return super(procurement_order, self)._check(cr, uid, procurement, context=context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -87,7 +87,6 @@ class ir_http(orm.AbstractModel):
# to url without language so google doesn't see duplicate content
return request.redirect(path + '?' + request.httprequest.query_string)
return self.reroute(path)
return self._handle_exception(code=404)
return super(ir_http, self)._dispatch()
def reroute(self, path):
@ -115,8 +114,8 @@ class ir_http(orm.AbstractModel):
try:
_, path = rule.build(arguments)
assert path is not None
except Exception:
return self._handle_exception(werkzeug.exceptions.NotFound())
except Exception, e:
return self._handle_exception(e, code=404)
if getattr(request, 'website_multilang', False) and request.httprequest.method in ('GET', 'HEAD'):
generated_path = werkzeug.url_unquote_plus(path)
@ -148,55 +147,70 @@ class ir_http(orm.AbstractModel):
if response.status_code == 304:
return response
response.mimetype = attach[0]['mimetype']
response.mimetype = attach[0]['mimetype'] or 'application/octet-stream'
response.data = datas.decode('base64')
return response
def _handle_exception(self, exception=None, code=500):
try:
def _handle_exception(self, exception, code=500):
# This is done first as the attachment path may
# not match any HTTP controller, so the request
# may not be website-enabled.
attach = self._serve_attachment()
if attach:
return attach
is_website_request = bool(getattr(request, 'website_enabled', False) and request.website)
if not is_website_request:
# Don't touch non website requests exception handling
return super(ir_http, self)._handle_exception(exception)
except Exception:
else:
try:
response = super(ir_http, self)._handle_exception(exception)
if isinstance(response, Exception):
exception = response
else:
# if parent excplicitely returns a plain response, then we don't touch it
return response
except Exception, e:
exception = e
attach = self._serve_attachment()
if attach:
return attach
values = dict(
exception=exception,
traceback=traceback.format_exc(exception),
)
code = getattr(exception, 'code', code)
if getattr(request, 'website_enabled', False) and request.website:
values = dict(
exception=exception,
traceback=traceback.format_exc(exception),
)
if exception:
code = getattr(exception, 'code', code)
if isinstance(exception, ir_qweb.QWebException):
values.update(qweb_exception=exception)
if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
code = 403
if code == 500:
logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
if 'qweb_exception' in values:
view = request.registry.get("ir.ui.view")
views = view._views_get(request.cr, request.uid, exception.qweb['template'], request.context)
to_reset = [v for v in views if v.model_data_id.noupdate is True]
values['views'] = to_reset
elif code == 403:
logger.warn("403 Forbidden:\n\n%s", values['traceback'])
if isinstance(exception, openerp.exceptions.AccessError):
code = 403
values.update(
status_message=werkzeug.http.HTTP_STATUS_CODES[code],
status_code=code,
)
if isinstance(exception, ir_qweb.QWebException):
values.update(qweb_exception=exception)
if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
code = 403
if not request.uid:
self._auth_method_public()
if code == 500:
logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
if 'qweb_exception' in values:
view = request.registry.get("ir.ui.view")
views = view._views_get(request.cr, request.uid, exception.qweb['template'], request.context)
to_reset = [v for v in views if v.model_data_id.noupdate is True]
values['views'] = to_reset
elif code == 403:
logger.warn("403 Forbidden:\n\n%s", values['traceback'])
try:
html = request.website._render('website.%s' % code, values)
except Exception:
html = request.website._render('website.http_error', values)
return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8')
values.update(
status_message=werkzeug.http.HTTP_STATUS_CODES[code],
status_code=code,
)
raise
if not request.uid:
self._auth_method_public()
try:
html = request.website._render('website.%s' % code, values)
except Exception:
html = request.website._render('website.http_error', values)
return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8')
class ModelConverter(ir.ir_http.ModelConverter):
def __init__(self, url_map, model=False, domain='[]'):

View File

@ -208,12 +208,16 @@ class WebsiteForum(http.Controller):
}, context=context)
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), new_question_id))
@http.route(['''/forum/<model("forum.forum"):forum>/question/<model("forum.post", "[('forum_id','=',forum[0])]"):question>'''], type='http', auth="public", website=True)
@http.route(['''/forum/<model("forum.forum"):forum>/question/<model("forum.post", "[('forum_id','=',forum[0]),('parent_id','=',False)]"):question>'''], type='http', auth="public", website=True)
def question(self, forum, question, **post):
cr, uid, context = request.cr, request.uid, request.context
# increment view counter
request.registry['forum.post'].set_viewed(cr, SUPERUSER_ID, [question.id], context=context)
if question.parent_id:
redirect_url = "/forum/%s/question/%s" % (slug(forum), slug(question.parent_id))
return werkzeug.utils.redirect(redirect_url, 301)
filters = 'question'
values = self._prepare_forum_values(forum=forum, searches=post)
values.update({

View File

@ -1266,7 +1266,10 @@ class Root(object):
request = self.get_request(httprequest)
def _dispatch_nodb():
func, arguments = self.nodb_routing_map.bind_to_environ(request.httprequest.environ).match()
try:
func, arguments = self.nodb_routing_map.bind_to_environ(request.httprequest.environ).match()
except werkzeug.exceptions.HTTPException, e:
return request._handle_exception(e)
request.set_handler(func, arguments, "none")
result = request.dispatch()
return result