[MERGE] forward port branch saas-12 up to 0ca99ff

This commit is contained in:
Christophe Simonis
2016-11-02 17:56:37 +01:00
11 changed files with 49 additions and 22 deletions
@@ -645,8 +645,9 @@ class AccountBankStatementLine(models.Model):
# Look for a single move line with the same amount
field = currency and 'amount_residual_currency' or 'amount_residual'
liquidity_field = currency and 'amount_currency' or amount > 0 and 'debit' or 'credit'
liquidity_amt_clause = currency and '%(amount)s' or 'abs(%(amount)s)'
sql_query = self._get_common_sql_query(excluded_ids=excluded_ids) + \
" AND ("+field+" = %(amount)s OR (acc.internal_type = 'liquidity' AND "+liquidity_field+" = %(amount)s)) \
" AND ("+field+" = %(amount)s OR (acc.internal_type = 'liquidity' AND "+liquidity_field+" = " + liquidity_amt_clause + ")) \
ORDER BY date_maturity asc, aml.id asc LIMIT 1"
self.env.cr.execute(sql_query, params)
results = self.env.cr.fetchone()
+4 -2
View File
@@ -218,9 +218,10 @@ class HrExpense(models.Model):
raise UserError(_("No Home Address found for the employee %s, please configure one.") % (expense.employee_id.name))
emp_account = expense.employee_id.address_home_id.property_account_payable_id.id
aml_name = expense.employee_id.name + ': ' + expense.name.split('\n')[0][:64]
move_lines.append({
'type': 'dest',
'name': expense.employee_id.name,
'name': aml_name,
'price': total,
'account_id': emp_account,
'date_maturity': acc_date,
@@ -253,9 +254,10 @@ class HrExpense(models.Model):
if not account:
raise UserError(_('Please configure Default Expense account for Product expense: `property_account_expense_categ_id`.'))
aml_name = expense.employee_id.name + ': ' + expense.name.split('\n')[0][:64]
move_line = {
'type': 'src',
'name': expense.name.split('\n')[0][:64],
'name': aml_name,
'price_unit': expense.unit_amount,
'quantity': expense.quantity,
'price': expense.total_amount,
@@ -141,6 +141,7 @@
<field name="uom_id" ref="product.product_uom_kgm" />
<field name="uom_po_id" ref="product.product_uom_kgm" />
<field name="image" type="base64" file="point_of_sale/static/img/peche-image.jpg"/>
<field name="taxes_id" eval='[(5,)]'/> <!-- no taxes -->
</record>
<record id="raisins_noir" model="product.product">
+4 -1
View File
@@ -4,6 +4,7 @@
from datetime import timedelta
from odoo import api, fields, models
from odoo.tools.safe_eval import safe_eval
class ProjectTaskType(models.Model):
@@ -104,7 +105,9 @@ class Project(models.Model):
def action_view_task_rating(self):
""" return the action to see all the rating about the tasks of the project """
action = self.env['ir.actions.act_window'].for_xml_id('rating', 'action_view_rating')
return dict(action, domain=[('res_id', 'in', self.tasks.ids), ('res_model', '=', 'project.task')])
action_domain = safe_eval(action['domain']) if action['domain'] else []
domain = action_domain + [('res_id', 'in', self.tasks.ids), ('res_model', '=', 'project.task')]
return dict(action, domain=domain)
@api.multi
def action_view_all_rating(self):
@@ -4,6 +4,7 @@
from datetime import timedelta
from odoo import api, fields, models
from odoo.tools.safe_eval import safe_eval
class ProjectIssue(models.Model):
@@ -28,7 +29,6 @@ class ProjectIssue(models.Model):
return super(ProjectIssue, self).rating_apply(rate, token=token, feedback=feedback, subtype="rating_project_issue.mt_issue_rating")
class Stage(models.Model):
_inherit = ['project.task.type']
@@ -45,7 +45,7 @@ class Project(models.Model):
def _send_rating_mail(self):
super(Project, self)._send_rating_mail()
for project in self:
project.issue_ids._send_issue_rating_mail()
self.env['project.issue'].search([('project_id', '=', project.id)])._send_issue_rating_mail()
@api.depends('percentage_satisfaction_task', 'percentage_satisfaction_issue')
def _compute_percentage_satisfaction_project(self):
@@ -58,7 +58,7 @@ class Project(models.Model):
activity_great = activity_task['great']
activity_sum = sum(activity_task.values())
if project.use_issues:
activity_issue = project.issue_ids.rating_get_grades(domain)
activity_issue = self.env['project.issue'].search([('project_id', '=', project.id)]).rating_get_grades(domain)
activity_great += activity_issue['great']
activity_sum += sum(activity_issue.values())
project.percentage_satisfaction_project = activity_great * 100 / activity_sum if activity_sum else -1
@@ -77,7 +77,9 @@ class Project(models.Model):
""" return the action to see all the rating about the issues of the project """
action = self.env['ir.actions.act_window'].for_xml_id('rating', 'action_view_rating')
issues = self.env['project.issue'].search([('project_id', 'in', self.ids)])
return dict(action, domain=[('res_id', 'in', issues.ids), ('res_model', '=', 'project.issue')])
action_domain = safe_eval(action['domain']) if action['domain'] else []
domain = action_domain + [('res_id', 'in', issues.ids), ('res_model', '=', 'project.issue')]
return dict(action, domain=domain)
@api.multi
def action_view_all_rating(self):
+9
View File
@@ -108,6 +108,15 @@ class PickingType(models.Model):
res.append((picking_type.id, name))
return res
@api.model
def name_search(self, name, args=None, operator='ilike', limit=100):
args = args or []
domain = []
if name:
domain = ['|', ('name', operator, name), ('warehouse_id.name', operator, name)]
picks = self.search(domain + args, limit=limit)
return picks.name_get()
@api.onchange('code')
def onchange_picking_code(self):
if self.code == 'incoming':
+10 -7
View File
@@ -2302,13 +2302,16 @@ eventHandler.modules.popover.update = function ($popover, oStyle, isAirMode) {
}
};
options.onPaste = function (e) {
e.preventDefault(); // FIXME this does not work with our custom out-dated summernote.
document.execCommand("undo"); // FIXME ... so use this hack until we decide to do something about it.
var pastedText = ((e.originalEvent || e).clipboardData || window.clipboardData).getData('Text');
var formattedText = pastedText.replace(/([^.!?:;])\r?\n/g, "$1").trim(); // Remove linebreaks which are not at the end of a sentence
document.execCommand("insertText", false, formattedText);
// override summernote clipboard functionality
eventHandler.modules.clipboard.attach = function(layoutInfo) {
var $editable = layoutInfo.editable();
$editable.on('paste', function(e) {
e.preventDefault();
$editable.data('NoteHistory').recordUndo($editable);
var pastedText = ((e.originalEvent || e).clipboardData || window.clipboardData).getData('Text');
var formattedText = pastedText.replace(/([^.!?:;])\r?\n/g, "$1").trim(); // Remove linebreaks which are not at the end of a sentence
document.execCommand("insertText", false, formattedText);
});
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
+2 -3
View File
@@ -166,14 +166,13 @@ class Http(models.AbstractModel):
langs = [lg[0] for lg in request.website.get_languages()]
path = request.httprequest.path.split('/')
if first_pass:
is_a_bot = cls.is_a_bot()
nearest_lang = not func and cls.get_nearest_lang(path[1])
url_lang = nearest_lang and path[1]
preferred_lang = ((cook_lang if cook_lang in langs else False)
or cls.get_nearest_lang(request.lang)
or (not is_a_bot and cls.get_nearest_lang(request.lang))
or request.website.default_lang_code)
is_a_bot = cls.is_a_bot()
request.lang = context['lang'] = nearest_lang or preferred_lang
# if lang in url but not the displayed or default language --> change or remove
# or no lang in url, and lang to dispay not the default language --> add lang
@@ -241,7 +241,7 @@
<h4 class="text-center text-muted"
t-field="event.address_id" t-options='{
"widget": "contact",
"fields": ["address", "phone", "mobile", "fax"]
"fields": ["name", "address", "phone", "mobile", "fax"]
}'/>
</t>
</template>
@@ -342,7 +342,7 @@
</t>
<div itemprop="location" class="mt16 mb8" t-field="event.address_id" t-options='{
"widget": "contact",
"fields": ["address", "phone", "mobile", "fax", "email"]
"fields": ["name", "address", "phone", "mobile", "fax", "email"]
}'/>
</div>
</div>
@@ -521,7 +521,7 @@
<i class="fa fa-clock-o"/> <span itemprop="startDate" t-esc="event.date_begin_located[:-3]"> </span> <i>to</i> <span itemprop="endDate" t-esc="event.date_end_located[:-3]"> </span>
<div itemprop="location" class="mt16 mb8" t-field="event.address_id" t-options='{
"widget": "contact",
"fields": ["address", "phone", "mobile", "fax", "email"]
"fields": ["name", "address", "phone", "mobile", "fax", "email"]
}'/>
</div>
<div class="col-md-3 mt16">
@@ -692,7 +692,12 @@
<t t-foreach="quotations" t-as="quotation">
<tr>
<td>
<a t-attf-href="/quote/#{quotation.id}?#{keep_query()}"><t t-esc="quotation.name"/></a>
<t t-if="quotation.sudo().partner_id.commercial_partner_id != request.env.user.partner_id.commercial_partner_id and request.env.user.share">
<a t-attf-href="/quote/#{quotation.id}/#{quotation.access_token}?#{keep_query()}"><t t-esc="quotation.name"/></a>
</t>
<t t-if="not (quotation.sudo().partner_id.commercial_partner_id != request.env.user.partner_id.commercial_partner_id and request.env.user.share)">
<a t-attf-href="/quote/#{quotation.id}?#{keep_query()}"><t t-esc="quotation.name"/></a>
</t>
</td>
<td><span t-field="quotation.validity_date"/></td>
<td>
+2
View File
@@ -86,6 +86,8 @@ class BaseCase(unittest.TestCase):
initialized by subclasses.
"""
longMessage = True # more verbose error message by default: https://www.odoo.com/r/Vmh
def cursor(self):
return self.registry.cursor()