[MERGE] forward port branch saas-14 up to b857fd4c90
This commit is contained in:
@@ -892,7 +892,7 @@ class AccountBankStatementLine(models.Model):
|
|||||||
counterpart_moves = (counterpart_moves | move)
|
counterpart_moves = (counterpart_moves | move)
|
||||||
|
|
||||||
# Create The payment
|
# Create The payment
|
||||||
payment = False
|
payment = self.env['account.payment']
|
||||||
if abs(total)>0.00001:
|
if abs(total)>0.00001:
|
||||||
partner_id = self.partner_id and self.partner_id.id or False
|
partner_id = self.partner_id and self.partner_id.id or False
|
||||||
partner_type = False
|
partner_type = False
|
||||||
|
|||||||
@@ -707,7 +707,7 @@ class AccountInvoice(models.Model):
|
|||||||
total_currency = 0
|
total_currency = 0
|
||||||
for line in invoice_move_lines:
|
for line in invoice_move_lines:
|
||||||
if self.currency_id != company_currency:
|
if self.currency_id != company_currency:
|
||||||
currency = self.currency_id.with_context(date=self.date_invoice or fields.Date.context_today(self))
|
currency = self.currency_id.with_context(date=self.date or self.date_invoice or fields.Date.context_today(self))
|
||||||
if not (line.get('currency_id') and line.get('amount_currency')):
|
if not (line.get('currency_id') and line.get('amount_currency')):
|
||||||
line['currency_id'] = currency.id
|
line['currency_id'] = currency.id
|
||||||
line['amount_currency'] = currency.round(line['price'])
|
line['amount_currency'] = currency.round(line['price'])
|
||||||
@@ -841,7 +841,6 @@ class AccountInvoice(models.Model):
|
|||||||
|
|
||||||
if not inv.date_invoice:
|
if not inv.date_invoice:
|
||||||
inv.with_context(ctx).write({'date_invoice': fields.Date.context_today(self)})
|
inv.with_context(ctx).write({'date_invoice': fields.Date.context_today(self)})
|
||||||
date_invoice = inv.date_invoice
|
|
||||||
company_currency = inv.company_id.currency_id
|
company_currency = inv.company_id.currency_id
|
||||||
|
|
||||||
# create move lines (one per invoice line + eventual taxes and analytic lines)
|
# create move lines (one per invoice line + eventual taxes and analytic lines)
|
||||||
@@ -854,9 +853,9 @@ class AccountInvoice(models.Model):
|
|||||||
|
|
||||||
name = inv.name or '/'
|
name = inv.name or '/'
|
||||||
if inv.payment_term_id:
|
if inv.payment_term_id:
|
||||||
totlines = inv.with_context(ctx).payment_term_id.with_context(currency_id=company_currency.id).compute(total, date_invoice)[0]
|
totlines = inv.with_context(ctx).payment_term_id.with_context(currency_id=company_currency.id).compute(total, inv.date_invoice)[0]
|
||||||
res_amount_currency = total_currency
|
res_amount_currency = total_currency
|
||||||
ctx['date'] = date_invoice
|
ctx['date'] = inv.date or inv.date_invoice
|
||||||
for i, t in enumerate(totlines):
|
for i, t in enumerate(totlines):
|
||||||
if inv.currency_id != company_currency:
|
if inv.currency_id != company_currency:
|
||||||
amount_currency = company_currency.with_context(ctx).compute(t[1], inv.currency_id)
|
amount_currency = company_currency.with_context(ctx).compute(t[1], inv.currency_id)
|
||||||
@@ -896,7 +895,7 @@ class AccountInvoice(models.Model):
|
|||||||
journal = inv.journal_id.with_context(ctx)
|
journal = inv.journal_id.with_context(ctx)
|
||||||
line = inv.finalize_invoice_move_lines(line)
|
line = inv.finalize_invoice_move_lines(line)
|
||||||
|
|
||||||
date = inv.date or date_invoice
|
date = inv.date or inv.date_invoice
|
||||||
move_vals = {
|
move_vals = {
|
||||||
'ref': inv.reference,
|
'ref': inv.reference,
|
||||||
'line_ids': line,
|
'line_ids': line,
|
||||||
@@ -1494,6 +1493,12 @@ class AccountPaymentTerm(models.Model):
|
|||||||
result.append((last_date, dist))
|
result.append((last_date, dist))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def unlink(self):
|
||||||
|
property_recs = self.env['ir.property'].search([('value_reference', 'in', ['account.payment.term,%s'%payment_term.id for payment_term in self])])
|
||||||
|
property_recs.unlink()
|
||||||
|
return super(AccountPaymentTerm, self).unlink()
|
||||||
|
|
||||||
|
|
||||||
class AccountPaymentTermLine(models.Model):
|
class AccountPaymentTermLine(models.Model):
|
||||||
_name = "account.payment.term.line"
|
_name = "account.payment.term.line"
|
||||||
|
|||||||
@@ -57,10 +57,16 @@ Best Regards,''')
|
|||||||
if (date.month < last_month or (date.month == last_month and date.day <= last_day)):
|
if (date.month < last_month or (date.month == last_month and date.day <= last_day)):
|
||||||
date = date.replace(month=last_month, day=last_day)
|
date = date.replace(month=last_month, day=last_day)
|
||||||
else:
|
else:
|
||||||
date = date.replace(month=last_month, day=last_day, year=date.year + 1)
|
if last_month == 2 and last_day == 29 and (date.year + 1) % 4 != 0:
|
||||||
|
date = date.replace(month=last_month, day=28, year=date.year + 1)
|
||||||
|
else:
|
||||||
|
date = date.replace(month=last_month, day=last_day, year=date.year + 1)
|
||||||
date_to = date
|
date_to = date
|
||||||
date_from = date + timedelta(days=1)
|
date_from = date + timedelta(days=1)
|
||||||
date_from = date_from.replace(year=date_from.year - 1)
|
if date_from.month == 2 and date_from.day == 29:
|
||||||
|
date_from = date_from.replace(day=28, year=date_from.year - 1)
|
||||||
|
else:
|
||||||
|
date_from = date_from.replace(year=date_from.year - 1)
|
||||||
return {'date_from': date_from, 'date_to': date_to}
|
return {'date_from': date_from, 'date_to': date_to}
|
||||||
|
|
||||||
def get_new_account_code(self, current_code, old_prefix, new_prefix, digits):
|
def get_new_account_code(self, current_code, old_prefix, new_prefix, digits):
|
||||||
|
|||||||
@@ -200,7 +200,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<div class="alert alert-info info_icon" role="alert">
|
<div class="alert alert-info info_icon" role="alert">
|
||||||
<span class="fa fa-lightbulb-o fa-lg"/>
|
<span class="fa fa-lightbulb-o fa-lg"/>
|
||||||
<p>Exchange rates can be automatically updated once a day from <strong>Yahoo Finance</strong> or the <strong>European Central Bank</strong>. You can activate this feature in the bottom of the <a t-att-href="prepare_backend_url('account.action_account_config')">Accounting Settings</a><a t-att-href="prepare_backend_url('account.action_account_config')">accounting settings</a>.</p>
|
<p>Exchange rates can be automatically updated once a day from <strong>Yahoo Finance</strong> or the <strong>European Central Bank</strong>. You can activate this feature in the bottom of the <a t-att-href="prepare_backend_url('account.action_account_config')">Accounting Settings</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
</t>
|
</t>
|
||||||
<t t-call="web_planner.page">
|
<t t-call="web_planner.page">
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ class AccountBankStatementImport(models.TransientModel):
|
|||||||
else:
|
else:
|
||||||
ignored_statement_lines_import_ids.append(line_vals['unique_import_id'])
|
ignored_statement_lines_import_ids.append(line_vals['unique_import_id'])
|
||||||
if 'balance_start' in st_vals:
|
if 'balance_start' in st_vals:
|
||||||
st_vals['balance_start'] += line_vals['amount']
|
st_vals['balance_start'] += float(line_vals['amount'])
|
||||||
|
|
||||||
if len(filtered_st_lines) > 0:
|
if len(filtered_st_lines) > 0:
|
||||||
# Remove values that won't be used to create records
|
# Remove values that won't be used to create records
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<field name="name">Submitted</field>
|
<field name="name">Submitted</field>
|
||||||
<field name="res_model">hr.expense.sheet</field>
|
<field name="res_model">hr.expense.sheet</field>
|
||||||
<field name="description">Expense report submitted, waiting approval</field>
|
<field name="description">Expense report submitted, waiting approval</field>
|
||||||
<field name="default" eval="False"/>
|
<field name="default" eval="True"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="mt_expense_paid" model="mail.message.subtype">
|
<record id="mt_expense_paid" model="mail.message.subtype">
|
||||||
<field name="name">Paid</field>
|
<field name="name">Paid</field>
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ class HrExpense(models.Model):
|
|||||||
company_id = fields.Many2one('res.company', string='Company', readonly=True, states={'draft': [('readonly', False)], 'refused': [('readonly', False)]}, default=lambda self: self.env.user.company_id)
|
company_id = fields.Many2one('res.company', string='Company', readonly=True, states={'draft': [('readonly', False)], 'refused': [('readonly', False)]}, default=lambda self: self.env.user.company_id)
|
||||||
currency_id = fields.Many2one('res.currency', string='Currency', readonly=True, states={'draft': [('readonly', False)], 'refused': [('readonly', False)]}, default=lambda self: self.env.user.company_id.currency_id)
|
currency_id = fields.Many2one('res.currency', string='Currency', readonly=True, states={'draft': [('readonly', False)], 'refused': [('readonly', False)]}, default=lambda self: self.env.user.company_id.currency_id)
|
||||||
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account', states={'post': [('readonly', True)], 'done': [('readonly', True)]}, oldname='analytic_account')
|
analytic_account_id = fields.Many2one('account.analytic.account', string='Analytic Account', states={'post': [('readonly', True)], 'done': [('readonly', True)]}, oldname='analytic_account')
|
||||||
account_id = fields.Many2one('account.account', string='Account', states={'post': [('readonly', True)], 'done': [('readonly', True)]}, default=lambda self: self.env['ir.property'].get('property_account_expense_categ_id', 'product.category'))
|
account_id = fields.Many2one('account.account', string='Account', states={'post': [('readonly', True)], 'done': [('readonly', True)]}, default=lambda self: self.env['ir.property'].get('property_account_expense_categ_id', 'product.category'),
|
||||||
|
help="An expense account is expected")
|
||||||
description = fields.Text()
|
description = fields.Text()
|
||||||
payment_mode = fields.Selection([("own_account", "Employee (to reimburse)"), ("company_account", "Company")], default='own_account', states={'done': [('readonly', True)], 'post': [('readonly', True)]}, string="Payment By")
|
payment_mode = fields.Selection([("own_account", "Employee (to reimburse)"), ("company_account", "Company")], default='own_account', states={'done': [('readonly', True)], 'post': [('readonly', True)]}, string="Payment By")
|
||||||
attachment_number = fields.Integer(compute='_compute_attachment_number', string='Number of Attachments')
|
attachment_number = fields.Integer(compute='_compute_attachment_number', string='Number of Attachments')
|
||||||
@@ -418,10 +419,15 @@ class HrExpenseSheet(models.Model):
|
|||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
|
# Add the followers at creation, so they can be notified
|
||||||
|
if vals.get('employee_id'):
|
||||||
|
employee = self.env['hr.employee'].browse(vals['employee_id'])
|
||||||
|
users = self._get_users_to_subscribe(employee=employee) - self.env.user
|
||||||
|
vals['message_follower_ids'] = []
|
||||||
|
for partner in users.mapped('partner_id'):
|
||||||
|
vals['message_follower_ids'] += self.env['mail.followers']._add_follower_command(self._name, [], {partner.id: None}, {})[0]
|
||||||
sheet = super(HrExpenseSheet, self).create(vals)
|
sheet = super(HrExpenseSheet, self).create(vals)
|
||||||
self.check_consistency()
|
self.check_consistency()
|
||||||
if vals.get('employee_id'):
|
|
||||||
sheet._add_followers()
|
|
||||||
return sheet
|
return sheet
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@@ -456,16 +462,20 @@ class HrExpenseSheet(models.Model):
|
|||||||
return 'hr_expense.mt_expense_paid'
|
return 'hr_expense.mt_expense_paid'
|
||||||
return super(HrExpenseSheet, self)._track_subtype(init_values)
|
return super(HrExpenseSheet, self)._track_subtype(init_values)
|
||||||
|
|
||||||
def _add_followers(self):
|
def _get_users_to_subscribe(self, employee=False):
|
||||||
user_ids = []
|
users = self.env['res.users']
|
||||||
employee = self.employee_id
|
employee = employee or self.employee_id
|
||||||
if employee.user_id:
|
if employee.user_id:
|
||||||
user_ids.append(employee.user_id.id)
|
users |= employee.user_id
|
||||||
if employee.parent_id:
|
if employee.parent_id:
|
||||||
user_ids.append(employee.parent_id.user_id.id)
|
users |= employee.parent_id.user_id
|
||||||
if employee.department_id and employee.department_id.manager_id and employee.parent_id != employee.department_id.manager_id:
|
if employee.department_id and employee.department_id.manager_id and employee.parent_id != employee.department_id.manager_id:
|
||||||
user_ids.append(employee.department_id.manager_id.user_id.id)
|
users |= employee.department_id.manager_id.user_id
|
||||||
self.message_subscribe_users(user_ids=user_ids)
|
return users
|
||||||
|
|
||||||
|
def _add_followers(self):
|
||||||
|
users = self._get_users_to_subscribe()
|
||||||
|
self.message_subscribe_users(user_ids=users.ids)
|
||||||
|
|
||||||
@api.onchange('employee_id')
|
@api.onchange('employee_id')
|
||||||
def _onchange_employee_id(self):
|
def _onchange_employee_id(self):
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
</group><group>
|
</group><group>
|
||||||
<field name="reference"/>
|
<field name="reference"/>
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
<field name="account_id"/>
|
<field name="account_id" domain="[('internal_type', '=', 'other')]"/>
|
||||||
<field name="employee_id"/>
|
<field name="employee_id"/>
|
||||||
<field name="sheet_id" invisible="1"/>
|
<field name="sheet_id" invisible="1"/>
|
||||||
<field name="currency_id" groups="base.group_multi_currency"/>
|
<field name="currency_id" groups="base.group_multi_currency"/>
|
||||||
|
|||||||
@@ -2906,6 +2906,7 @@
|
|||||||
<field name="name">Coupons échus à l'encaissement</field>
|
<field name="name">Coupons échus à l'encaissement</field>
|
||||||
<field name="code">5111</field>
|
<field name="code">5111</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_liquidity"/>
|
<field name="user_type_id" ref="account.data_account_type_liquidity"/>
|
||||||
|
<field name="reconcile" eval="True"/>
|
||||||
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
|
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@@ -2913,6 +2914,7 @@
|
|||||||
<field name="name">Chèques à encaisser</field>
|
<field name="name">Chèques à encaisser</field>
|
||||||
<field name="code">5112</field>
|
<field name="code">5112</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_liquidity"/>
|
<field name="user_type_id" ref="account.data_account_type_liquidity"/>
|
||||||
|
<field name="reconcile" eval="True"/>
|
||||||
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
|
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@@ -2920,6 +2922,7 @@
|
|||||||
<field name="name">Effets à l'encaissement</field>
|
<field name="name">Effets à l'encaissement</field>
|
||||||
<field name="code">5113</field>
|
<field name="code">5113</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_liquidity"/>
|
<field name="user_type_id" ref="account.data_account_type_liquidity"/>
|
||||||
|
<field name="reconcile" eval="True"/>
|
||||||
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
|
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@@ -2927,6 +2930,7 @@
|
|||||||
<field name="name">Effets à l'escompte</field>
|
<field name="name">Effets à l'escompte</field>
|
||||||
<field name="code">5114</field>
|
<field name="code">5114</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_liquidity"/>
|
<field name="user_type_id" ref="account.data_account_type_liquidity"/>
|
||||||
|
<field name="reconcile" eval="True"/>
|
||||||
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
|
<field name="chart_template_id" ref="l10n_fr_pcg_chart_template"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,7 @@
|
|||||||
<field name="name">equipment.request.calendar</field>
|
<field name="name">equipment.request.calendar</field>
|
||||||
<field name="model">maintenance.request</field>
|
<field name="model">maintenance.request</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<calendar date_start="schedule_date" color="technician_user_id">
|
<calendar date_start="schedule_date" color="technician_user_id" date_delay="duration">
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="technician_user_id"/>
|
<field name="technician_user_id"/>
|
||||||
</calendar>
|
</calendar>
|
||||||
|
|||||||
@@ -61,15 +61,14 @@ class MailMail(models.Model):
|
|||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
body = super(MailMail, self).send_get_mail_body(partner=partner)
|
body = super(MailMail, self).send_get_mail_body(partner=partner)
|
||||||
|
|
||||||
links_blacklist = ['/unsubscribe_from_list']
|
|
||||||
|
|
||||||
if self.mailing_id and body and self.statistics_ids:
|
if self.mailing_id and body and self.statistics_ids:
|
||||||
for match in re.findall(URL_REGEX, self.body_html):
|
for match in re.findall(URL_REGEX, self.body_html):
|
||||||
|
|
||||||
href = match[0]
|
href = match[0]
|
||||||
url = match[1]
|
url = match[1]
|
||||||
|
|
||||||
if not [s for s in links_blacklist if s in href]:
|
parsed = urlparse.urlparse(url, scheme='http')
|
||||||
|
|
||||||
|
if parsed.scheme.startswith('http') and parsed.path.startswith('/r/'):
|
||||||
new_href = href.replace(url, url + '/m/' + str(self.statistics_ids[0].id))
|
new_href = href.replace(url, url + '/m/' + str(self.statistics_ids[0].id))
|
||||||
body = body.replace(href, new_href)
|
body = body.replace(href, new_href)
|
||||||
|
|
||||||
|
|||||||
@@ -39,3 +39,13 @@ class MailThread(models.AbstractModel):
|
|||||||
message_ids = [x.strip() for x in decode_smtp_header(message['References']).split()]
|
message_ids = [x.strip() for x in decode_smtp_header(message['References']).split()]
|
||||||
self.env['mail.mail.statistics'].set_replied(mail_message_ids=message_ids)
|
self.env['mail.mail.statistics'].set_replied(mail_message_ids=message_ids)
|
||||||
return super(MailThread, self).message_route_process(message, message_dict, routes)
|
return super(MailThread, self).message_route_process(message, message_dict, routes)
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def message_post_with_template(self, template_id, **kwargs):
|
||||||
|
# avoid having message send through `message_post*` methods being implicitly considered as
|
||||||
|
# mass-mailing
|
||||||
|
no_massmail = self.with_context(
|
||||||
|
default_mass_mailing_name=False,
|
||||||
|
default_mass_mailing_id=False,
|
||||||
|
)
|
||||||
|
return super(MailThread, no_massmail).message_post_with_template(template_id, **kwargs)
|
||||||
|
|||||||
@@ -226,11 +226,12 @@ class Repair(models.Model):
|
|||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_repair_invoice_create(self):
|
def action_repair_invoice_create(self):
|
||||||
self.action_invoice_create()
|
for repair in self:
|
||||||
if self.invoice_method == 'b4repair':
|
repair.action_invoice_create()
|
||||||
self.action_repair_ready()
|
if repair.invoice_method == 'b4repair':
|
||||||
elif self.invoice_method == 'after_repair':
|
repair.action_repair_ready()
|
||||||
self.write({'state': 'done'})
|
elif repair.invoice_method == 'after_repair':
|
||||||
|
repair.write({'state': 'done'})
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
|
|||||||
@@ -256,14 +256,14 @@ class TxAuthorize(models.Model):
|
|||||||
def authorize_s2s_capture_transaction(self):
|
def authorize_s2s_capture_transaction(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
transaction = AuthorizeAPI(self.acquirer_id)
|
transaction = AuthorizeAPI(self.acquirer_id)
|
||||||
tree = transaction.capture(self.acquirer_reference, self.amount)
|
tree = transaction.capture(self.acquirer_reference or '', self.amount)
|
||||||
return self._authorize_s2s_validate_tree(tree)
|
return self._authorize_s2s_validate_tree(tree)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def authorize_s2s_void_transaction(self):
|
def authorize_s2s_void_transaction(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
transaction = AuthorizeAPI(self.acquirer_id)
|
transaction = AuthorizeAPI(self.acquirer_id)
|
||||||
tree = transaction.void(self.acquirer_reference)
|
tree = transaction.void(self.acquirer_reference or '')
|
||||||
return self._authorize_s2s_validate_tree(tree)
|
return self._authorize_s2s_validate_tree(tree)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
|
|||||||
@@ -625,7 +625,7 @@ class PosOrder(models.Model):
|
|||||||
return_picking = Picking.create(return_vals)
|
return_picking = Picking.create(return_vals)
|
||||||
return_picking.message_post(body=message)
|
return_picking.message_post(body=message)
|
||||||
|
|
||||||
for line in order.lines.filtered(lambda l: l.product_id.type in ['product', 'consu']):
|
for line in order.lines.filtered(lambda l: l.product_id.type in ['product', 'consu'] and not float_is_zero(l.qty, precision_digits=l.product_id.uom_id.rounding)):
|
||||||
moves |= Move.create({
|
moves |= Move.create({
|
||||||
'name': line.name,
|
'name': line.name,
|
||||||
'product_uom': line.product_id.uom_id.id,
|
'product_uom': line.product_id.uom_id.id,
|
||||||
|
|||||||
@@ -10,27 +10,20 @@ class SaleOrderLine(models.Model):
|
|||||||
@api.multi
|
@api.multi
|
||||||
def _compute_analytic(self, domain=None):
|
def _compute_analytic(self, domain=None):
|
||||||
lines = {}
|
lines = {}
|
||||||
|
force_so_lines = self.env.context.get("force_so_lines")
|
||||||
if not domain:
|
if not domain:
|
||||||
|
if not self.ids and not force_so_lines:
|
||||||
|
return True
|
||||||
# To filter on analyic lines linked to an expense
|
# To filter on analyic lines linked to an expense
|
||||||
expense_type_id = self.env.ref('account.data_account_type_expenses', raise_if_not_found=False)
|
expense_type_id = self.env.ref('account.data_account_type_expenses', raise_if_not_found=False)
|
||||||
expense_type_id = expense_type_id and expense_type_id.id
|
expense_type_id = expense_type_id and expense_type_id.id
|
||||||
domain = [
|
domain = [('so_line', 'in', self.ids), ('amount', '<=', 0.0)]
|
||||||
('so_line', 'in', self.ids),
|
|
||||||
'|',
|
|
||||||
('amount', '<', 0),
|
|
||||||
'&',
|
|
||||||
('amount', '=', 0),
|
|
||||||
'|',
|
|
||||||
('move_id', '=', False),
|
|
||||||
('move_id.account_id.user_type_id', '=', expense_type_id)
|
|
||||||
]
|
|
||||||
|
|
||||||
data = self.env['account.analytic.line'].read_group(
|
data = self.env['account.analytic.line'].read_group(
|
||||||
domain,
|
domain,
|
||||||
['so_line', 'unit_amount', 'product_uom_id'], ['product_uom_id', 'so_line'], lazy=False
|
['so_line', 'unit_amount', 'product_uom_id'], ['product_uom_id', 'so_line'], lazy=False
|
||||||
)
|
)
|
||||||
# If the unlinked analytic line was the last one on the SO line, the qty was not updated.
|
# If the unlinked analytic line was the last one on the SO line, the qty was not updated.
|
||||||
force_so_lines = self.env.context.get("force_so_lines")
|
|
||||||
if force_so_lines:
|
if force_so_lines:
|
||||||
for line in force_so_lines:
|
for line in force_so_lines:
|
||||||
lines.setdefault(line, 0.0)
|
lines.setdefault(line, 0.0)
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ class SaleAdvancePaymentInv(models.TransientModel):
|
|||||||
'payment_term_id': order.payment_term_id.id,
|
'payment_term_id': order.payment_term_id.id,
|
||||||
'fiscal_position_id': order.fiscal_position_id.id or order.partner_id.property_account_position_id.id,
|
'fiscal_position_id': order.fiscal_position_id.id or order.partner_id.property_account_position_id.id,
|
||||||
'team_id': order.team_id.id,
|
'team_id': order.team_id.id,
|
||||||
|
'user_id': order.user_id.id,
|
||||||
'comment': order.note,
|
'comment': order.note,
|
||||||
})
|
})
|
||||||
invoice.compute_taxes()
|
invoice.compute_taxes()
|
||||||
|
|||||||
@@ -140,20 +140,9 @@ class SaleOrderLine(models.Model):
|
|||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _compute_analytic(self, domain=None):
|
def _compute_analytic(self, domain=None):
|
||||||
if not domain:
|
if not domain and self.ids:
|
||||||
# To filter on analyic lines linked to an expense
|
# To filter on analyic lines linked to an expense
|
||||||
expense_type_id = self.env.ref('account.data_account_type_expenses', raise_if_not_found=False)
|
expense_type_id = self.env.ref('account.data_account_type_expenses', raise_if_not_found=False)
|
||||||
expense_type_id = expense_type_id and expense_type_id.id
|
expense_type_id = expense_type_id and expense_type_id.id
|
||||||
domain = [
|
domain = [('so_line', 'in', self.ids), '|', ('amount', '<=', 0.0), ('project_id', '!=', False)]
|
||||||
('so_line', 'in', self.ids),
|
|
||||||
'|',
|
|
||||||
'|',
|
|
||||||
('amount', '<', 0.0),
|
|
||||||
('project_id', '!=', False),
|
|
||||||
'&',
|
|
||||||
('amount', '=', 0),
|
|
||||||
'|',
|
|
||||||
('move_id', '=', False),
|
|
||||||
('move_id.account_id.user_type_id', '=', expense_type_id)
|
|
||||||
]
|
|
||||||
return super(SaleOrderLine, self)._compute_analytic(domain=domain)
|
return super(SaleOrderLine, self)._compute_analytic(domain=domain)
|
||||||
|
|||||||
@@ -364,6 +364,12 @@ class Product(models.Model):
|
|||||||
def action_view_routes(self):
|
def action_view_routes(self):
|
||||||
return self.mapped('product_tmpl_id').action_view_routes()
|
return self.mapped('product_tmpl_id').action_view_routes()
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def write(self, values):
|
||||||
|
res = super(Product, self).write(values)
|
||||||
|
if 'active' in values and not values['active'] and self.mapped('orderpoint_ids').filtered(lambda r: r.active):
|
||||||
|
raise UserError(_('You still have some active reordering rules on this product. Please archive or delete them first.'))
|
||||||
|
return res
|
||||||
|
|
||||||
class ProductTemplate(models.Model):
|
class ProductTemplate(models.Model):
|
||||||
_inherit = 'product.template'
|
_inherit = 'product.template'
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class SaleQuoteTemplate(models.Model):
|
|||||||
], 'Payment', help="Require immediate payment by the customer when validating the order from the website quote")
|
], 'Payment', help="Require immediate payment by the customer when validating the order from the website quote")
|
||||||
mail_template_id = fields.Many2one('mail.template', 'Confirmation Mail',
|
mail_template_id = fields.Many2one('mail.template', 'Confirmation Mail',
|
||||||
help="This e-mail template will be sent on confirmation. Leave empty to send nothing.",
|
help="This e-mail template will be sent on confirmation. Leave empty to send nothing.",
|
||||||
domain=[('model', '=', 'sale.quote.template')])
|
domain=[('model', '=', 'sale.order')])
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def open_template(self):
|
def open_template(self):
|
||||||
|
|||||||
@@ -135,12 +135,18 @@ if(!$('.o_website_quote').length) {
|
|||||||
case "h1":
|
case "h1":
|
||||||
var id = self.setElementId('quote_header_', el);
|
var id = self.setElementId('quote_header_', el);
|
||||||
var text = self.extractText($(el));
|
var text = self.extractText($(el));
|
||||||
|
if (!text) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
last_li = $("<li>").append($('<a href="#'+id+'"/>').text(text)).appendTo(self.$el);
|
last_li = $("<li>").append($('<a href="#'+id+'"/>').text(text)).appendTo(self.$el);
|
||||||
last_ul = false;
|
last_ul = false;
|
||||||
break;
|
break;
|
||||||
case "h2":
|
case "h2":
|
||||||
var id = self.setElementId('quote_', el);
|
var id = self.setElementId('quote_', el);
|
||||||
var text = self.extractText($(el));
|
var text = self.extractText($(el));
|
||||||
|
if (!text) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (last_li) {
|
if (last_li) {
|
||||||
if (!last_ul) {
|
if (!last_ul) {
|
||||||
last_ul = $("<ul class='nav'>").appendTo(last_li);
|
last_ul = $("<ul class='nav'>").appendTo(last_li);
|
||||||
|
|||||||
@@ -170,7 +170,7 @@
|
|||||||
<div class="products_pager">
|
<div class="products_pager">
|
||||||
<div class="row" style="width: 100%;">
|
<div class="row" style="width: 100%;">
|
||||||
<t t-call="website_sale.search">
|
<t t-call="website_sale.search">
|
||||||
<t t-set="search_class">pagination form-inline o_website_sale_search</t>
|
<t t-set="search_class" t-value="'pagination form-inline o_website_sale_search'"/>
|
||||||
</t>
|
</t>
|
||||||
<t t-call="website_sale.pricelist_list" />
|
<t t-call="website_sale.pricelist_list" />
|
||||||
<t t-call="website.pager" />
|
<t t-call="website.pager" />
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
Finland, 2017-07-17
|
||||||
|
|
||||||
|
Oy Tawasta OS Technologies Ltd. agrees to the terms of the Odoo Corporate Contributor License Agreement v1.0.
|
||||||
|
|
||||||
|
We declare that we are authorized and able to make this agreement and sign this declaration.
|
||||||
|
|
||||||
|
Signed,
|
||||||
|
|
||||||
|
Jarmo Kortetjärvi jarmo.kortetjarvi@tawasta.fi https://github.com/jarmokortetjarvi
|
||||||
|
|
||||||
|
List of contributors:
|
||||||
|
|
||||||
|
Aleksi Savijoki aleksi.savijoki@tawasta.fi https://github.com/savijoki
|
||||||
|
Jarmo Kortetjärvi jarmo.kortetjarvi@tawasta.fi https://github.com/jarmokortetjarvi
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
India, 2017-07-04
|
||||||
|
|
||||||
|
I hereby agree to the terms of the Odoo Individual Contributor License Agreement v1.0.
|
||||||
|
|
||||||
|
I declare that I am authorized and able to make this agreement and sign this declaration.
|
||||||
|
|
||||||
|
Signed,
|
||||||
|
|
||||||
|
Rakesh Sindhav sindhav21591@gmail.com https://github.com/sindhav
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
Finland, 2017-07-19
|
||||||
|
|
||||||
|
I hereby agree to the terms of the Odoo Individual Contributor License
|
||||||
|
Agreement v1.0.
|
||||||
|
|
||||||
|
I declare that I am authorized and able to make this agreement and sign this
|
||||||
|
declaration.
|
||||||
|
|
||||||
|
Signed,
|
||||||
|
|
||||||
|
Timo Talvitie timo.talvitie@vizucom.com https://github.com/timotalvitie
|
||||||
@@ -11,7 +11,7 @@ diff --git a/openacademy/models.py b/openacademy/models.py
|
|||||||
+from datetime import timedelta
|
+from datetime import timedelta
|
||||||
from odoo import models, fields, api, exceptions
|
from odoo import models, fields, api, exceptions
|
||||||
|
|
||||||
class Session(models.Model):
|
class Course(models.Model):
|
||||||
@@ -55,6 +56,8 @@ class Session(models.Model):
|
@@ -55,6 +56,8 @@ class Session(models.Model):
|
||||||
attendee_ids = fields.Many2many('res.partner', string="Attendees")
|
attendee_ids = fields.Many2many('res.partner', string="Attendees")
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Index: addons/openacademy/views/openacademy.xml
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- addons.orig/openacademy/views/openacademy.xml 2014-08-28 14:21:58.627015606 +0200
|
--- addons.orig/openacademy/views/openacademy.xml 2014-08-28 14:21:58.627015606 +0200
|
||||||
+++ addons/openacademy/views/openacademy.xml 2014-08-28 14:21:58.623015606 +0200
|
+++ addons/openacademy/views/openacademy.xml 2014-08-28 14:21:58.623015606 +0200
|
||||||
@@ -169,11 +169,57 @@
|
@@ -168,11 +168,57 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ dictionary, where each key specifies module metadatum.
|
|||||||
""",
|
""",
|
||||||
# data files always loaded at installation
|
# data files always loaded at installation
|
||||||
'data': [
|
'data': [
|
||||||
'mymodule_view.xml',
|
'views/mymodule_view.xml',
|
||||||
],
|
],
|
||||||
# data files containing optionally loaded demonstration data
|
# data files containing optionally loaded demonstration data
|
||||||
'demo': [
|
'demo': [
|
||||||
'demo_data.xml',
|
'demo/demo_data.xml',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user