[FIX] Forward-port of saas-5 up to 0d330ca
This commit is contained in:
commit
668b8c2b2d
|
@ -19,9 +19,6 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# 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.osv import fields, osv
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
|
@ -55,7 +52,7 @@ class purchase_requisition(osv.osv):
|
||||||
'procurement_id': fields.many2one('procurement.order', 'Procurement', ondelete='set null'),
|
'procurement_id': fields.many2one('procurement.order', 'Procurement', ondelete='set null'),
|
||||||
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
|
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'),
|
||||||
'state': fields.selection([('draft', 'Draft'), ('in_progress', 'Confirmed'), ('open', 'Bid Selection'), ('done', 'PO Created'), ('cancel', 'Cancelled')],
|
'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'),
|
'multiple_rfq_per_supplier': fields.boolean('Multiple RFQ per supplier'),
|
||||||
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'),
|
'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'),
|
||||||
'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', required=True),
|
'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):
|
def _get_picking_in(self, cr, uid, context=None):
|
||||||
obj_data = self.pool.get('ir.model.data')
|
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 = {
|
_defaults = {
|
||||||
'state': 'draft',
|
'state': 'draft',
|
||||||
|
@ -85,14 +82,11 @@ class purchase_requisition(osv.osv):
|
||||||
|
|
||||||
def tender_cancel(self, cr, uid, ids, context=None):
|
def tender_cancel(self, cr, uid, ids, context=None):
|
||||||
purchase_order_obj = self.pool.get('purchase.order')
|
purchase_order_obj = self.pool.get('purchase.order')
|
||||||
#try to set all associated quotations to cancel state
|
# try to set all associated quotations to cancel state
|
||||||
purchase_ids = []
|
|
||||||
for tender in self.browse(cr, uid, ids, context=context):
|
for tender in self.browse(cr, uid, ids, context=context):
|
||||||
for purchase_order in tender.purchase_ids:
|
for purchase_order in tender.purchase_ids:
|
||||||
purchase_order_obj.action_cancel(cr, uid, [purchase_order.id], context=context)
|
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)
|
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'})
|
return self.write(cr, uid, ids, {'state': 'cancel'})
|
||||||
|
|
||||||
def tender_in_progress(self, cr, uid, ids, context=None):
|
def tender_in_progress(self, cr, uid, ids, context=None):
|
||||||
|
@ -110,8 +104,6 @@ class purchase_requisition(osv.osv):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def tender_done(self, cr, uid, ids, context=None):
|
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)
|
return self.write(cr, uid, ids, {'state': 'done'}, context=context)
|
||||||
|
|
||||||
def open_product_line(self, cr, uid, ids, context=None):
|
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)
|
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)
|
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
|
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,
|
vals = po_line_obj.onchange_product_id(
|
||||||
supplier.id, date_order=date_order, fiscal_position_id=supplier.property_account_position, date_planned=requisition_line.schedule_date,
|
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']
|
name=False, price_unit=False, state='draft', context=context)['value']
|
||||||
vals.update({
|
vals.update({
|
||||||
'order_id': purchase_id,
|
'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
|
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')
|
po = self.pool.get('purchase.order')
|
||||||
poline = self.pool.get('purchase.order.line')
|
poline = self.pool.get('purchase.order.line')
|
||||||
id_per_supplier = {}
|
id_per_supplier = {}
|
||||||
|
@ -271,8 +264,7 @@ class purchase_requisition(osv.osv):
|
||||||
id_per_supplier[po_line.partner_id.id] = [po_line]
|
id_per_supplier[po_line.partner_id.id] = [po_line]
|
||||||
|
|
||||||
#generate po based on supplier and cancel all previous RFQ
|
#generate po based on supplier and cancel all previous RFQ
|
||||||
ctx = context.copy()
|
ctx = dict(context or {}, force_requisition_id=True)
|
||||||
ctx['force_requisition_id'] = True
|
|
||||||
for supplier, product_line in id_per_supplier.items():
|
for supplier, product_line in id_per_supplier.items():
|
||||||
#copy a quotation for this supplier and change order_line then validate it
|
#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]
|
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})
|
proc_obj.write(cr, uid, proc_ids, {'purchase_id': po.id})
|
||||||
self.signal_purchase_cancel(cr, uid, [order.id])
|
self.signal_purchase_cancel(cr, uid, [order.id])
|
||||||
po.requisition_id.tender_done(context=context)
|
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
|
return res
|
||||||
|
|
||||||
def copy(self, cr, uid, id, default=None, context=None):
|
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)
|
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
|
||||||
|
|
||||||
def _check(self, cr, uid, procurement, context=None):
|
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.rule_id and procurement.rule_id.action == 'buy' and procurement.product_id.purchase_requisition:
|
||||||
if procurement.requisition_id.state == 'done':
|
if procurement.requisition_id.state == 'done':
|
||||||
if any([purchase.shipped for purchase in procurement.requisition_id.purchase_ids]):
|
if any([purchase.shipped for purchase in procurement.requisition_id.purchase_ids]):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
return super(procurement_order, self)._check(cr, uid, procurement, context=context)
|
return super(procurement_order, self)._check(cr, uid, procurement, context=context)
|
||||||
|
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
||||||
|
|
|
@ -87,7 +87,6 @@ class ir_http(orm.AbstractModel):
|
||||||
# to url without language so google doesn't see duplicate content
|
# to url without language so google doesn't see duplicate content
|
||||||
return request.redirect(path + '?' + request.httprequest.query_string)
|
return request.redirect(path + '?' + request.httprequest.query_string)
|
||||||
return self.reroute(path)
|
return self.reroute(path)
|
||||||
return self._handle_exception(code=404)
|
|
||||||
return super(ir_http, self)._dispatch()
|
return super(ir_http, self)._dispatch()
|
||||||
|
|
||||||
def reroute(self, path):
|
def reroute(self, path):
|
||||||
|
@ -115,8 +114,8 @@ class ir_http(orm.AbstractModel):
|
||||||
try:
|
try:
|
||||||
_, path = rule.build(arguments)
|
_, path = rule.build(arguments)
|
||||||
assert path is not None
|
assert path is not None
|
||||||
except Exception:
|
except Exception, e:
|
||||||
return self._handle_exception(werkzeug.exceptions.NotFound())
|
return self._handle_exception(e, code=404)
|
||||||
|
|
||||||
if getattr(request, 'website_multilang', False) and request.httprequest.method in ('GET', 'HEAD'):
|
if getattr(request, 'website_multilang', False) and request.httprequest.method in ('GET', 'HEAD'):
|
||||||
generated_path = werkzeug.url_unquote_plus(path)
|
generated_path = werkzeug.url_unquote_plus(path)
|
||||||
|
@ -148,55 +147,70 @@ class ir_http(orm.AbstractModel):
|
||||||
if response.status_code == 304:
|
if response.status_code == 304:
|
||||||
return response
|
return response
|
||||||
|
|
||||||
response.mimetype = attach[0]['mimetype']
|
response.mimetype = attach[0]['mimetype'] or 'application/octet-stream'
|
||||||
response.data = datas.decode('base64')
|
response.data = datas.decode('base64')
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def _handle_exception(self, exception=None, code=500):
|
def _handle_exception(self, exception, code=500):
|
||||||
try:
|
# 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)
|
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()
|
values = dict(
|
||||||
if attach:
|
exception=exception,
|
||||||
return attach
|
traceback=traceback.format_exc(exception),
|
||||||
|
)
|
||||||
|
code = getattr(exception, 'code', code)
|
||||||
|
|
||||||
if getattr(request, 'website_enabled', False) and request.website:
|
if isinstance(exception, openerp.exceptions.AccessError):
|
||||||
values = dict(
|
code = 403
|
||||||
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'])
|
|
||||||
|
|
||||||
values.update(
|
if isinstance(exception, ir_qweb.QWebException):
|
||||||
status_message=werkzeug.http.HTTP_STATUS_CODES[code],
|
values.update(qweb_exception=exception)
|
||||||
status_code=code,
|
if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
|
||||||
)
|
code = 403
|
||||||
|
|
||||||
if not request.uid:
|
if code == 500:
|
||||||
self._auth_method_public()
|
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:
|
values.update(
|
||||||
html = request.website._render('website.%s' % code, values)
|
status_message=werkzeug.http.HTTP_STATUS_CODES[code],
|
||||||
except Exception:
|
status_code=code,
|
||||||
html = request.website._render('website.http_error', values)
|
)
|
||||||
return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8')
|
|
||||||
|
|
||||||
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):
|
class ModelConverter(ir.ir_http.ModelConverter):
|
||||||
def __init__(self, url_map, model=False, domain='[]'):
|
def __init__(self, url_map, model=False, domain='[]'):
|
||||||
|
|
|
@ -208,12 +208,16 @@ class WebsiteForum(http.Controller):
|
||||||
}, context=context)
|
}, context=context)
|
||||||
return werkzeug.utils.redirect("/forum/%s/question/%s" % (slug(forum), new_question_id))
|
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):
|
def question(self, forum, question, **post):
|
||||||
cr, uid, context = request.cr, request.uid, request.context
|
cr, uid, context = request.cr, request.uid, request.context
|
||||||
# increment view counter
|
# increment view counter
|
||||||
request.registry['forum.post'].set_viewed(cr, SUPERUSER_ID, [question.id], context=context)
|
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'
|
filters = 'question'
|
||||||
values = self._prepare_forum_values(forum=forum, searches=post)
|
values = self._prepare_forum_values(forum=forum, searches=post)
|
||||||
values.update({
|
values.update({
|
||||||
|
|
|
@ -1266,7 +1266,10 @@ class Root(object):
|
||||||
request = self.get_request(httprequest)
|
request = self.get_request(httprequest)
|
||||||
|
|
||||||
def _dispatch_nodb():
|
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")
|
request.set_handler(func, arguments, "none")
|
||||||
result = request.dispatch()
|
result = request.dispatch()
|
||||||
return result
|
return result
|
||||||
|
|
Loading…
Reference in New Issue