[MERGE] Sync with saas-2

bzr revid: tde@openerp.com-20131104105827-gbpsn66twnon20rw
This commit is contained in:
Thibault Delavallée 2013-11-04 11:58:27 +01:00
commit d1c5c84a85
20 changed files with 138 additions and 122 deletions

View File

@ -107,14 +107,15 @@ class res_partner(osv.osv):
_description = 'Partner'
def _credit_debit_get(self, cr, uid, ids, field_names, arg, context=None):
query = self.pool.get('account.move.line')._query_get(cr, uid, context=context)
ctx = context.copy()
ctx['all_fiscalyear'] = True
query = self.pool.get('account.move.line')._query_get(cr, uid, context=ctx)
cr.execute("""SELECT l.partner_id, a.type, SUM(l.debit-l.credit)
FROM account_move_line l
LEFT JOIN account_account a ON (l.account_id=a.id)
WHERE a.type IN ('receivable','payable')
AND l.partner_id IN %s
AND (l.reconcile_id IS NULL OR
reconcile_id in (SELECT id FROM account_move_reconcile WHERE opening_reconciliation is TRUE))
AND l.reconcile_id IS NULL
AND """ + query + """
GROUP BY l.partner_id, a.type
""",

View File

@ -51,7 +51,12 @@ openerp.base_import = function (instance) {
type: 'ir.actions.client',
tag: 'import',
params: {
model: self.dataset.model
model: self.dataset.model,
// self.dataset.get_context() could be a compound?
// not sure. action's context should be evaluated
// so safer bet. Odd that timezone & al in it
// though
context: self.getParent().action.context,
}
}, {
on_reverse_breadcrumb: function () {
@ -127,6 +132,7 @@ openerp.base_import = function (instance) {
var self = this;
this._super.apply(this, arguments);
this.res_model = action.params.model;
this.parent_context = action.params.context || {};
// import object id
this.id = null;
this.Import = new instance.web.Model('base_import.import');
@ -353,11 +359,12 @@ openerp.base_import = function (instance) {
},
//- import itself
call_import: function (options) {
call_import: function (kwargs) {
var fields = this.$('.oe_import_fields input.oe_import_match_field').map(function (index, el) {
return $(el).select2('val') || false;
}).get();
return this.Import.call('do', [this.id, fields, this.import_options()], options)
kwargs.context = this.parent_context;
return this.Import.call('do', [this.id, fields, this.import_options()], kwargs)
.then(undefined, function (error, event) {
// In case of unexpected exception, convert
// "JSON-RPC error" to an import failure, and

View File

@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
# Copyright (C) 2010-2012 OpenERP s.a. (<http://openerp.com>).
# Copyright (C) 2010-2013 OpenERP s.a. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -49,6 +49,7 @@ class board_board(osv.osv):
('value', 'in', refs),
], context=context)
menu_ids = map(itemgetter('res_id'), IrValues.read(cr, uid, irv_ids, ['res_id'], context=context))
menu_ids = Menus._filter_visible_menus(cr, uid, menu_ids, context=context)
menu_names = Menus.name_get(cr, uid, menu_ids, context=context)
return [dict(id=m[0], name=m[1]) for m in menu_names]

View File

@ -79,8 +79,8 @@ class crm_case_stage(osv.osv):
}
_defaults = {
'sequence': lambda *args: 1,
'probability': lambda *args: 0.0,
'sequence': 1,
'probability': 0.0,
'on_change': True,
'fold': False,
'type': 'both',

View File

@ -120,7 +120,7 @@
<field name="date"/>
<field name="name"/>
<field name="partner_id"
on_change="onchange_partner_id(partner_id)"/>
on_change="on_change_partner_id(partner_id)"/>
<field name="partner_phone"
invisible="1"/>
<field name="user_id" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads']}"/>

View File

@ -59,11 +59,11 @@ class crm_lead2opportunity_partner(osv.osv_memory):
if partner_id:
# Search for opportunities that have the same partner and that arent done or cancelled
ids = lead_obj.search(cr, uid, [('partner_id', '=', partner_id), ('probability', '<', '100')])
ids = lead_obj.search(cr, uid, [('partner_id', '=', partner_id), '|', ('probability', '=', False), ('probability', '<', '100')])
for id in ids:
tomerge.add(id)
if email:
ids = lead_obj.search(cr, uid, [('email_from', '=ilike', email[0]), ('probability', '<', '100')])
ids = lead_obj.search(cr, uid, [('email_from', '=ilike', email[0]), '|', ('probability', '=', False), ('probability', '<', '100')])
for id in ids:
tomerge.add(id)

View File

@ -179,6 +179,12 @@ class crm_lead(osv.osv):
return res
def assign_geo_localize(self, cr, uid, ids, latitude=False, longitude=False, context=None):
if latitude and longitude:
self.write(cr, uid, ids, {
'partner_latitude': latitude,
'partner_longitude': longitude
}, context=context)
return True
# Don't pass context to browse()! We need country name in english below
for lead in self.browse(cr, uid, ids):
if not lead.country_id:
@ -188,14 +194,11 @@ class crm_lead(osv.osv):
city=lead.city,
state=lead.state_id.name,
country=lead.country_id.name))
if not latitude and result:
latitude = result[0]
if not longitude and result:
longitude = result[1]
self.write(cr, uid, [lead.id], {
'partner_latitude': latitude,
'partner_longitude': longitude
}, context=context)
if result:
self.write(cr, uid, [lead.id], {
'partner_latitude': result[0],
'partner_longitude': result[1]
}, context=context)
return True
def search_geo_partner(self, cr, uid, ids, context=None):

View File

@ -4,14 +4,14 @@
<record model="crm.case.stage" id="stage_portal_lead_assigned">
<field name="name">Assigned</field>
<field eval="1" name="case_default"/>
<field eval="0" name="probability"/>
<field eval="10" name="probability"/>
<field eval="12" name="sequence"/>
<field name="type">lead</field>
</record>
<record model="crm.case.stage" id="stage_portal_lead_recycle">
<field name="name">To Recycle</field>
<field eval="1" name="case_default"/>
<field eval="0" name="probability"/>
<field eval="5" name="probability"/>
<field eval="11" name="sequence"/>
<field name="type">lead</field>
</record>
@ -31,7 +31,7 @@
<ol>
% for lead in ctx['partner_leads']:
<li><a href="${lead.lead_link}">${lead.lead_id.name or 'Subject Undefined'}</a>, ${lead.lead_id.contact_name or 'Contact Name Undefined'}, ${lead.lead_id.country_id and lead.lead_id.country_id.name or 'Country Undefined' }, ${lead.lead_id.email_from or 'Email Undefined'}, ${lead.lead_id.phone or ''} </li></br>
<li><a href="${lead.lead_link}">${lead.lead_id.name or 'Subject Undefined'}</a>, ${lead.lead_id.partner_name or lead.lead_id.contact_name or 'Contact Name Undefined'}, ${lead.lead_id.country_id and lead.lead_id.country_id.name or 'Country Undefined' }, ${lead.lead_id.email_from or 'Email Undefined'}, ${lead.lead_id.phone or ''} </li></br>
% endfor
</ol>

View File

@ -236,11 +236,13 @@ class hr_employee(osv.osv):
employee_id = super(hr_employee, self).create(cr, uid, data, context=create_ctx)
employee = self.browse(cr, uid, employee_id, context=context)
if employee.user_id:
res_users = self.pool['res.users']
# send a copy to every user of the company
company_id = employee.user_id.partner_id.company_id.id
partner_ids = self.pool.get('res.partner').search(cr, uid, [
('company_id', '=', company_id),
('user_ids', '!=', False)], context=context)
# TODO: post to the `Whole Company` mail.group when we'll be able to link to the employee record
_model, group_id = self.pool['ir.model.data'].get_object_reference(cr, uid, 'base', 'group_user')
user_ids = res_users.search(cr, uid, [('company_id', '=', employee.user_id.company_id.id),
('groups_id', 'in', group_id)])
partner_ids = list(set(u.partner_id.id for u in res_users.browse(cr, uid, user_ids, context=context)))
else:
partner_ids = []
self.message_post(cr, uid, [employee_id],

View File

@ -117,7 +117,7 @@
<field name="model">hr.employee</field>
<field name="arch" type="xml">
<search string="Employees">
<field name="name" string="Employees"/>
<field name="name" string="Employees" filter_domain="['|',('work_email','ilike',self),('name','ilike',self)]"/>
<field name="department_id" />
<field name="category_ids" groups="base.group_hr_user"/>
<group expand="0" string="Group By...">

View File

@ -145,7 +145,9 @@ class hr_holidays(osv.osv):
def _check_date(self, cr, uid, ids):
for holiday in self.browse(cr, uid, ids):
holiday_ids = self.search(cr, uid, [('date_from', '<=', holiday.date_to), ('date_to', '>=', holiday.date_from), ('employee_id', '=', holiday.employee_id.id), ('id', '<>', holiday.id)])
holiday_ids = self.search(cr, uid, [('date_from', '<=', holiday.date_to), ('date_to', '>=', holiday.date_from),
('employee_id', '=', holiday.employee_id.id), ('id', '<>', holiday.id),
('state', 'not in', ['cancel', 'refuse'])])
if holiday_ids:
return False
return True

View File

@ -81,7 +81,8 @@
</record>
<record model="ir.actions.act_window" id="act_analytic_cost_revenue">
<field name="context">{'search_default_account_id': [active_id], 'default_account_id': active_id, 'search_default_group_date': 1, 'search_default_group_journal': 1}</field>
<field name="context">{'search_default_group_date': 1, 'search_default_group_journal': 1}</field>
<field name="domain">[('account_id','child_of', active_id)]</field>
<field name="name">Costs &amp; Revenues</field>
<field name="res_model">account.analytic.line</field>
<field name="src_model">account.analytic.account</field>

View File

@ -212,7 +212,7 @@ class mail_message(osv.Model):
_defaults = {
'type': 'email',
'date': fields.datetime.now(),
'date': fields.datetime.now,
'author_id': lambda self, cr, uid, ctx=None: self._get_default_author(cr, uid, ctx),
'body': '',
'email_from': lambda self, cr, uid, ctx=None: self._get_default_from(cr, uid, ctx),
@ -698,8 +698,9 @@ class mail_message(osv.Model):
"""
model_record_ids = {}
for id in msg_ids:
if msg_val[id]['model'] and msg_val[id]['res_id']:
model_record_ids.setdefault(msg_val[id]['model'], dict()).setdefault(msg_val[id]['res_id'], set()).add(msg_val[id]['res_id'])
vals = msg_val.get(id, {})
if vals.get('model') and vals.get('res_id'):
model_record_ids.setdefault(vals['model'], set()).add(vals['res_id'])
return model_record_ids
if uid == SUPERUSER_ID:
@ -711,7 +712,7 @@ class mail_message(osv.Model):
partner_id = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=None).partner_id.id
# Read mail_message.ids to have their values
message_values = dict.fromkeys(ids)
message_values = dict.fromkeys(ids, {})
cr.execute('SELECT DISTINCT id, model, res_id, author_id, parent_id FROM "%s" WHERE id = ANY (%%s)' % self._table, (ids,))
for id, rmod, rid, author_id, parent_id in cr.fetchall():
message_values[id] = {'model': rmod, 'res_id': rid, 'author_id': author_id, 'parent_id': parent_id}
@ -745,10 +746,10 @@ class mail_message(osv.Model):
], context=context)
notified_ids = [notification.message_id.id for notification in not_obj.browse(cr, SUPERUSER_ID, not_ids, context=context)]
elif operation == 'create':
for doc_model, doc_dict in model_record_ids.items():
for doc_model, doc_ids in model_record_ids.items():
fol_ids = fol_obj.search(cr, SUPERUSER_ID, [
('res_model', '=', doc_model),
('res_id', 'in', list(doc_dict.keys())),
('res_id', 'in', list(doc_ids)),
('partner_id', '=', partner_id),
], context=context)
fol_mids = [follower.res_id for follower in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)]
@ -759,9 +760,9 @@ class mail_message(osv.Model):
other_ids = other_ids.difference(set(notified_ids))
model_record_ids = _generate_model_record_ids(message_values, other_ids)
document_related_ids = []
for model, doc_dict in model_record_ids.items():
for model, doc_ids in model_record_ids.items():
model_obj = self.pool[model]
mids = model_obj.exists(cr, uid, doc_dict.keys())
mids = model_obj.exists(cr, uid, list(doc_ids))
if hasattr(model_obj, 'check_mail_message_access'):
model_obj.check_mail_message_access(cr, uid, mids, operation, context=context)
else:

View File

@ -577,7 +577,8 @@ class mail_thread(osv.AbstractModel):
return action
if msg_id and not (model and res_id):
msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context)
model, res_id = msg.model, msg.res_id
if msg.exists():
model, res_id = msg.model, msg.res_id
# if model + res_id found: try to redirect to the document or fallback on the Inbox
if model and res_id:

View File

@ -24,7 +24,6 @@ from openerp.osv import fields, osv
class crm_contact_us(osv.TransientModel):
""" Add employees list to the portal's contact page """
_inherit = 'portal_crm.crm_contact_us'
_description = 'Contact form for the portal'
_columns = {
'employee_ids' : fields.many2many('hr.employee', string='Employees', readonly=True),
}
@ -40,7 +39,6 @@ class crm_contact_us(osv.TransientModel):
}
class hr_employee(osv.osv):
_description = 'Portal employee'
_inherit = 'hr.employee'
"""

View File

@ -465,18 +465,20 @@ class project_issue(osv.Model):
return stage_ids[0]
return False
def case_escalate(self, cr, uid, ids, context=None):
cases = self.browse(cr, uid, ids)
for case in cases:
def case_escalate(self, cr, uid, ids, context=None): # FIXME rename this method to issue_escalate
for issue in self.browse(cr, uid, ids, context=context):
data = {}
if case.project_id.project_escalation_id:
data['project_id'] = case.project_id.project_escalation_id.id
if case.project_id.project_escalation_id.user_id:
data['user_id'] = case.project_id.project_escalation_id.user_id.id
if case.task_id:
self.pool.get('project.task').write(cr, uid, [case.task_id.id], {'project_id': data['project_id'], 'user_id': False})
else:
esc_proj = issue.project_id.project_escalation_id
if not esc_proj:
raise osv.except_osv(_('Warning!'), _('You cannot escalate this issue.\nThe relevant Project has not configured the Escalation Project!'))
data['project_id'] = esc_proj.id
if esc_proj.user_id:
data['user_id'] = esc_proj.user_id.id
issue.write(data)
if issue.task_id:
issue.task_id.write({'project_id': esc_proj.id, 'user_id': False})
return True
# -------------------------------------------------------

View File

@ -1234,17 +1234,27 @@ class account_invoice(osv.Model):
def invoice_validate(self, cr, uid, ids, context=None):
res = super(account_invoice, self).invoice_validate(cr, uid, ids, context=context)
purchase_order_obj = self.pool.get('purchase.order')
po_ids = purchase_order_obj.search(cr, uid, [('invoice_ids', 'in', ids)], context=context)
# read access on purchase.order object is not required
if not purchase_order_obj.check_access_rights(cr, uid, 'read', raise_exception=False):
user_id = SUPERUSER_ID
else:
user_id = uid
po_ids = purchase_order_obj.search(cr, user_id, [('invoice_ids', 'in', ids)], context=context)
for po_id in po_ids:
purchase_order_obj.message_post(cr, uid, po_id, body=_("Invoice received"), context=context)
purchase_order_obj.message_post(cr, user_id, po_id, body=_("Invoice received"), context=context)
return res
def confirm_paid(self, cr, uid, ids, context=None):
res = super(account_invoice, self).confirm_paid(cr, uid, ids, context=context)
purchase_order_obj = self.pool.get('purchase.order')
po_ids = purchase_order_obj.search(cr, uid, [('invoice_ids', 'in', ids)], context=context)
# read access on purchase.order object is not required
if not purchase_order_obj.check_access_rights(cr, uid, 'read', raise_exception=False):
user_id = SUPERUSER_ID
else:
user_id = uid
po_ids = purchase_order_obj.search(cr, user_id, [('invoice_ids', 'in', ids)], context=context)
if po_ids:
purchase_order_obj.message_post(cr, uid, po_ids, body=_("Invoice paid"), context=context)
purchase_order_obj.message_post(cr, user_id, po_ids, body=_("Invoice paid"), context=context)
return res
class account_invoice_line(osv.Model):

View File

@ -61,66 +61,49 @@ class report_stock_move(osv.osv):
cr.execute("""
CREATE OR REPLACE view report_stock_move AS (
SELECT
min(sm_id) as id,
date_trunc('day',al.dp) as date,
al.curr_year as year,
al.curr_month as month,
al.curr_day as day,
al.curr_day_diff as day_diff,
al.curr_day_diff1 as day_diff1,
al.curr_day_diff2 as day_diff2,
al.location_id as location_id,
al.picking_id as picking_id,
al.company_id as company_id,
al.location_dest_id as location_dest_id,
al.product_qty,
al.out_qty as product_qty_out,
al.in_qty as product_qty_in,
al.partner_id as partner_id,
al.product_id as product_id,
al.state as state ,
al.product_uom as product_uom,
al.categ_id as categ_id,
coalesce(al.type, 'other') as type,
al.stock_journal as stock_journal,
sum(al.in_value - al.out_value) as value
FROM (SELECT
CASE WHEN sp.type in ('out') THEN
sum(sm.product_qty * pu.factor / pu2.factor)
ELSE 0.0
END AS out_qty,
CASE WHEN sp.type in ('in') THEN
sum(sm.product_qty * pu.factor / pu2.factor)
ELSE 0.0
END AS in_qty,
CASE WHEN sp.type in ('out') THEN
sum(sm.product_qty * pu.factor / pu2.factor) * pt.standard_price
ELSE 0.0
END AS out_value,
CASE WHEN sp.type in ('in') THEN
sum(sm.product_qty * pu.factor / pu2.factor) * pt.standard_price
ELSE 0.0
END AS in_value,
min(sm.id) as sm_id,
sm.date as dp,
to_char(date_trunc('day',sm.date), 'YYYY') as curr_year,
to_char(date_trunc('day',sm.date), 'MM') as curr_month,
to_char(date_trunc('day',sm.date), 'YYYY-MM-DD') as curr_day,
avg(date(sm.date)-date(sm.create_date)) as curr_day_diff,
avg(date(sm.date_expected)-date(sm.create_date)) as curr_day_diff1,
avg(date(sm.date)-date(sm.date_expected)) as curr_day_diff2,
min(sm.id) as id,
date_trunc('day', sm.date) as date,
to_char(date_trunc('day',sm.date), 'YYYY') as year,
to_char(date_trunc('day',sm.date), 'MM') as month,
to_char(date_trunc('day',sm.date), 'YYYY-MM-DD') as day,
avg(date(sm.date)-date(sm.create_date)) as day_diff,
avg(date(sm.date_expected)-date(sm.create_date)) as day_diff1,
avg(date(sm.date)-date(sm.date_expected)) as day_diff2,
sm.location_id as location_id,
sm.picking_id as picking_id,
sm.company_id as company_id,
sm.location_dest_id as location_dest_id,
sum(sm.product_qty) as product_qty,
pt.categ_id as categ_id ,
sum(
(CASE WHEN sp.type in ('out') THEN
(sm.product_qty * pu.factor / pu2.factor)
ELSE 0.0
END)
) as product_qty_out,
sum(
(CASE WHEN sp.type in ('in') THEN
(sm.product_qty * pu.factor / pu2.factor)
ELSE 0.0
END)
) as product_qty_in,
sm.partner_id as partner_id,
sm.product_id as product_id,
sm.picking_id as picking_id,
sm.company_id as company_id,
sm.state as state,
sm.product_uom as product_uom,
sp.type as type,
sp.stock_journal_id AS stock_journal
sm.state as state,
sm.product_uom as product_uom,
pt.categ_id as categ_id ,
coalesce(sp.type, 'other') as type,
sp.stock_journal_id AS stock_journal,
sum(
(CASE WHEN sp.type in ('in') THEN
(sm.product_qty * pu.factor / pu2.factor) * pt.standard_price
ELSE 0.0
END)
-
(CASE WHEN sp.type in ('out') THEN
(sm.product_qty * pu.factor / pu2.factor) * pt.standard_price
ELSE 0.0
END)
) as value
FROM
stock_move sm
LEFT JOIN stock_picking sp ON (sm.picking_id=sp.id)
@ -129,16 +112,11 @@ class report_stock_move(osv.osv):
LEFT JOIN product_uom pu2 ON (sm.product_uom=pu2.id)
LEFT JOIN product_template pt ON (pp.product_tmpl_id=pt.id)
GROUP BY
sm.id,sp.type, sm.date,sm.partner_id,
sm.product_id,sm.state,sm.product_uom,sm.date_expected,
sm.product_id,pt.standard_price, sm.picking_id, sm.product_qty,
sm.company_id,sm.product_qty, sm.location_id,sm.location_dest_id,pu.factor,pt.categ_id, sp.stock_journal_id)
AS al
GROUP BY
al.out_qty,al.in_qty,al.curr_year,al.curr_month,
al.curr_day,al.curr_day_diff,al.curr_day_diff1,al.curr_day_diff2,al.dp,al.location_id,al.location_dest_id,
al.partner_id,al.product_id,al.state,al.product_uom,
al.picking_id,al.company_id,al.type,al.product_qty, al.categ_id, al.stock_journal
coalesce(sp.type, 'other'), date_trunc('day', sm.date), sm.partner_id,
sm.state, sm.product_uom, sm.date_expected,
sm.product_id, pt.standard_price, sm.picking_id,
sm.company_id, sm.location_id, sm.location_dest_id, pu.factor, pt.categ_id, sp.stock_journal_id,
year, month, day
)
""")

View File

@ -159,6 +159,10 @@ class stock_location(osv.osv):
\n* Production: Virtual counterpart location for production operations: this location consumes the raw material and produces finished products
""", select = True),
# temporarily removed, as it's unused: 'allocation_method': fields.selection([('fifo', 'FIFO'), ('lifo', 'LIFO'), ('nearest', 'Nearest')], 'Allocation Method', required=True),
# as discussed on bug 765559, the main purpose of this field is to allow sorting the list of locations
# according to the displayed names, and reversing that sort by clicking on a column. It does not work for
# translated values though - so it needs fixing.
'complete_name': fields.function(_complete_name, type='char', size=256, string="Location Name",
store={'stock.location': (_get_sublocations, ['name', 'location_id'], 10)}),

View File

@ -31,9 +31,14 @@ class invoice_directly(osv.osv_memory):
if context is None: context = {}
result = super(invoice_directly, self).do_partial(cr, uid, ids, context)
partial = self.browse(cr, uid, ids[0], context)
if partial.picking_id.state != 'done' and partial.picking_id.backorder_id:
# delivery is not finished, opening invoice on backorder
picking = partial.picking_id.backorder_id
else:
picking = partial.picking_id
context.update(active_model='stock.picking',
active_ids=[partial.picking_id.id])
if partial.picking_id.invoice_state == '2binvoiced':
active_ids=[picking.id])
if picking.invoice_state == '2binvoiced':
return {
'name': 'Create Invoice',
'view_type': 'form',