Merge branch 'master-harsh-06072018' into 'master-patch-july-2018'
Master harsh 06072018 See merge request flectra-hq/flectra!98
This commit is contained in:
commit
604cf9e3e0
@ -42,7 +42,7 @@
|
|||||||
<t t-set="page_title">Expense Types</t>
|
<t t-set="page_title">Expense Types</t>
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
The first step if to
|
The first step if to
|
||||||
<a href="https://www.flectra.com/documentation/user/11.0/expense/expense.html#how-to-set-expense-types" target="blank">
|
<a href="https://www.flectrahq.com/documentation/user/11.0/expense/expense.html#how-to-set-expense-types" target="blank">
|
||||||
configure the expense types
|
configure the expense types
|
||||||
</a>
|
</a>
|
||||||
that your company allows. Here are some examples:
|
that your company allows. Here are some examples:
|
||||||
@ -88,7 +88,7 @@
|
|||||||
<t t-set="page_title">Recording Mode</t>
|
<t t-set="page_title">Recording Mode</t>
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
As employees, there are
|
As employees, there are
|
||||||
<a href="https://www.flectra.com/documentation/user/11.0/expense/expense.html#how-to-record-expenses" target="_blank">2 ways to record expenses:</a>
|
<a href="https://www.flectrahq.com/documentation/user/11.0/expense/expense.html#how-to-record-expenses" target="_blank">2 ways to record expenses:</a>
|
||||||
</p>
|
</p>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
@ -128,7 +128,7 @@
|
|||||||
<a t-att-href="prepare_backend_url('base_setup.action_general_configuration')">
|
<a t-att-href="prepare_backend_url('base_setup.action_general_configuration')">
|
||||||
Set an email alias
|
Set an email alias
|
||||||
</a>
|
</a>
|
||||||
(e.g. expenses@mycompany.flectra.com)
|
(e.g. expenses@mycompany.flectrahq.com)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a t-att-href="prepare_backend_url('hr.open_view_employee_list_my', 'kanban')">
|
<a t-att-href="prepare_backend_url('hr.open_view_employee_list_my', 'kanban')">
|
||||||
@ -137,7 +137,7 @@
|
|||||||
(only such email addresses are authorized)
|
(only such email addresses are authorized)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="mailto:expenses@mycompany.flectra.com?subject=HrExpense%20Planner" target="_blank">
|
<a href="mailto:expenses@mycompany.flectrahq.com?subject=HrExpense%20Planner" target="_blank">
|
||||||
Send an expense by email
|
Send an expense by email
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@ -151,7 +151,7 @@
|
|||||||
<t t-set="page_title">Submit for Approval</t>
|
<t t-set="page_title">Submit for Approval</t>
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
The next step is to settle an internal policy to
|
The next step is to settle an internal policy to
|
||||||
<a href="https://www.flectra.com/documentation/user/11.0/expense/expense.html#how-to-submit-expenses-to-managers" target="_blank">submit expenses to managers
|
<a href="https://www.flectrahq.com/documentation/user/11.0/expense/expense.html#how-to-submit-expenses-to-managers" target="_blank">submit expenses to managers
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -189,7 +189,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
Depending on your company structure, the
|
Depending on your company structure, the
|
||||||
<a href="https://www.flectra.com/documentation/user/11.0/expense/expense.html#how-to-approve-expenses" target="_blank">approval process
|
<a href="https://www.flectrahq.com/documentation/user/11.0/expense/expense.html#how-to-approve-expenses" target="_blank">approval process
|
||||||
</a> can be:
|
</a> can be:
|
||||||
</p>
|
</p>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -243,7 +243,7 @@
|
|||||||
<t t-set="page_title">Reimbursement</t>
|
<t t-set="page_title">Reimbursement</t>
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
Once expense reports approved by managers, the accounting department checks accounts, products and taxes used. Then they
|
Once expense reports approved by managers, the accounting department checks accounts, products and taxes used. Then they
|
||||||
<a href="https://www.flectra.com/documentation/user/11.0/expense/expense.html#how-to-post-expenses-in-accounting" target="_blank"> post them into the books</a> and <a href="https://www.flectra.com/documentation/user/11.0/expense/expense.html#how-to-reimburse-employees" target="blank">proceed with the employee reimbursement</a>.
|
<a href="https://www.flectrahq.com/documentation/user/11.0/expense/expense.html#how-to-post-expenses-in-accounting" target="_blank"> post them into the books</a> and <a href="https://www.flectrahq.com/documentation/user/11.0/expense/expense.html#how-to-reimburse-employees" target="blank">proceed with the employee reimbursement</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
To do:
|
To do:
|
||||||
@ -258,7 +258,7 @@
|
|||||||
<a t-att-href="prepare_backend_url('hr.open_view_employee_list_my', 'kanban')">Set Home Address to employees</a>(used for reimbursement)
|
<a t-att-href="prepare_backend_url('hr.open_view_employee_list_my', 'kanban')">Set Home Address to employees</a>(used for reimbursement)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://www.flectra.com/documentation/user/11.0/accounting/payables.html" target="blank">See how to manage payables</a>
|
<a href="https://www.flectrahq.com/documentation/user/11.0/accounting/payables.html" target="blank">See how to manage payables</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
@ -267,7 +267,7 @@
|
|||||||
<t t-call="web_planner.page">
|
<t t-call="web_planner.page">
|
||||||
<t t-set="page_title">Invoice Customers</t>
|
<t t-set="page_title">Invoice Customers</t>
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
If you track expenses on customer projects, you can charge them <a href="https://www.flectra.com/documentation/user/11.0/expense/expense.html#how-to-re-invoice-expenses-to-your-customers" target="blank">back to your customers automatically</a>. Here are some advises to avoid conflictual situations:
|
If you track expenses on customer projects, you can charge them <a href="https://www.flectrahq.com/documentation/user/11.0/expense/expense.html#how-to-re-invoice-expenses-to-your-customers" target="blank">back to your customers automatically</a>. Here are some advises to avoid conflictual situations:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Agree in advance with the customer:
|
<li>Agree in advance with the customer:
|
||||||
@ -286,7 +286,7 @@
|
|||||||
<li><a t-att-href="prepare_backend_url('hr_expense.hr_expense_product', 'kanban')">Set invoicing method on expense products</a></li>
|
<li><a t-att-href="prepare_backend_url('hr_expense.hr_expense_product', 'kanban')">Set invoicing method on expense products</a></li>
|
||||||
<li><a t-att-href="prepare_backend_url('base.open_module_tree', 'form', 'sale')">Install Sales app</a></li>
|
<li><a t-att-href="prepare_backend_url('base.open_module_tree', 'form', 'sale')">Install Sales app</a></li>
|
||||||
<li><a t-att-href="prepare_backend_url('base.open_module_tree', 'form', 'account_analytic_default')">Install Analytic Accounting add-on</a></li>
|
<li><a t-att-href="prepare_backend_url('base.open_module_tree', 'form', 'account_analytic_default')">Install Analytic Accounting add-on</a></li>
|
||||||
<li><a href="https://www.flectra.com/documentation/user/11.0/expense/expense.html#how-to-re-invoice-expenses-to-your-customers" target="_blank">See how to invoice expenses</a></li>
|
<li><a href="https://www.flectrahq.com/documentation/user/11.0/expense/expense.html#how-to-re-invoice-expenses-to-your-customers" target="_blank">See how to invoice expenses</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
</t>
|
</t>
|
||||||
|
@ -215,3 +215,15 @@ class Employee(models.Model):
|
|||||||
('type', '=', 'remove')
|
('type', '=', 'remove')
|
||||||
])
|
])
|
||||||
return [('id', 'in', holidays.mapped('employee_id').ids)]
|
return [('id', 'in', holidays.mapped('employee_id').ids)]
|
||||||
|
|
||||||
|
def write(self, values):
|
||||||
|
res = super(Employee, self).write(values)
|
||||||
|
if 'parent_id' in values or 'department_id' in values:
|
||||||
|
holidays = self.env['hr.holidays'].search([('state', 'in', ['draft', 'confirm']), ('employee_id', 'in', self.ids)])
|
||||||
|
hr_vals = {}
|
||||||
|
if values.get('parent_id') is not None:
|
||||||
|
hr_vals['manager_id'] = values['parent_id']
|
||||||
|
if values.get('department_id') is not None:
|
||||||
|
hr_vals['department_id'] = values['department_id']
|
||||||
|
holidays.write(hr_vals)
|
||||||
|
return res
|
||||||
|
@ -180,7 +180,7 @@ class Holidays(models.Model):
|
|||||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
|
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
|
||||||
employee_id = fields.Many2one('hr.employee', string='Employee', index=True, readonly=True,
|
employee_id = fields.Many2one('hr.employee', string='Employee', index=True, readonly=True,
|
||||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, default=_default_employee, track_visibility='onchange')
|
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, default=_default_employee, track_visibility='onchange')
|
||||||
manager_id = fields.Many2one('hr.employee', related='employee_id.parent_id', string='Manager', readonly=True, store=True)
|
manager_id = fields.Many2one('hr.employee', string='Manager', readonly=True)
|
||||||
notes = fields.Text('Reasons', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
|
notes = fields.Text('Reasons', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
|
||||||
number_of_days_temp = fields.Float(
|
number_of_days_temp = fields.Float(
|
||||||
'Allocation', copy=False, readonly=True,
|
'Allocation', copy=False, readonly=True,
|
||||||
@ -195,9 +195,9 @@ class Holidays(models.Model):
|
|||||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]},
|
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]},
|
||||||
help="Choose 'Leave Request' if someone wants to take an off-day. "
|
help="Choose 'Leave Request' if someone wants to take an off-day. "
|
||||||
"\nChoose 'Allocation Request' if you want to increase the number of leaves available for someone")
|
"\nChoose 'Allocation Request' if you want to increase the number of leaves available for someone")
|
||||||
parent_id = fields.Many2one('hr.holidays', string='Parent')
|
parent_id = fields.Many2one('hr.holidays', string='Parent', copy=False)
|
||||||
linked_request_ids = fields.One2many('hr.holidays', 'parent_id', string='Linked Requests')
|
linked_request_ids = fields.One2many('hr.holidays', 'parent_id', string='Linked Requests')
|
||||||
department_id = fields.Many2one('hr.department', related='employee_id.department_id', string='Department', readonly=True, store=True)
|
department_id = fields.Many2one('hr.department', string='Department', readonly=True)
|
||||||
category_id = fields.Many2one('hr.employee.category', string='Employee Tag', readonly=True,
|
category_id = fields.Many2one('hr.employee.category', string='Employee Tag', readonly=True,
|
||||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Category of Employee')
|
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Category of Employee')
|
||||||
holiday_type = fields.Selection([
|
holiday_type = fields.Selection([
|
||||||
@ -248,7 +248,7 @@ class Holidays(models.Model):
|
|||||||
if nholidays:
|
if nholidays:
|
||||||
raise ValidationError(_('You can not have 2 leaves that overlaps on same day!'))
|
raise ValidationError(_('You can not have 2 leaves that overlaps on same day!'))
|
||||||
|
|
||||||
@api.constrains('state', 'number_of_days_temp')
|
@api.constrains('state', 'number_of_days_temp', 'holiday_status_id')
|
||||||
def _check_holidays(self):
|
def _check_holidays(self):
|
||||||
for holiday in self:
|
for holiday in self:
|
||||||
if holiday.holiday_type != 'employee' or holiday.type != 'remove' or not holiday.employee_id or holiday.holiday_status_id.limit:
|
if holiday.holiday_type != 'employee' or holiday.type != 'remove' or not holiday.employee_id or holiday.holiday_status_id.limit:
|
||||||
@ -274,7 +274,8 @@ class Holidays(models.Model):
|
|||||||
self.employee_id = None
|
self.employee_id = None
|
||||||
|
|
||||||
@api.onchange('employee_id')
|
@api.onchange('employee_id')
|
||||||
def _onchange_employee(self):
|
def _onchange_employee_id(self):
|
||||||
|
self.manager_id = self.employee_id and self.employee_id.parent_id
|
||||||
self.department_id = self.employee_id.department_id
|
self.department_id = self.employee_id.department_id
|
||||||
|
|
||||||
def _get_number_of_days(self, date_from, date_to, employee_id):
|
def _get_number_of_days(self, date_from, date_to, employee_id):
|
||||||
@ -358,6 +359,8 @@ class Holidays(models.Model):
|
|||||||
values.update({'department_id': self.env['hr.employee'].browse(employee_id).department_id.id})
|
values.update({'department_id': self.env['hr.employee'].browse(employee_id).department_id.id})
|
||||||
holiday = super(Holidays, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(values)
|
holiday = super(Holidays, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(values)
|
||||||
holiday.add_follower(employee_id)
|
holiday.add_follower(employee_id)
|
||||||
|
if 'employee_id' in values:
|
||||||
|
holiday._onchange_employee_id()
|
||||||
return holiday
|
return holiday
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@ -367,6 +370,8 @@ class Holidays(models.Model):
|
|||||||
raise AccessError(_('You cannot set a leave request as \'%s\'. Contact a human resource manager.') % values.get('state'))
|
raise AccessError(_('You cannot set a leave request as \'%s\'. Contact a human resource manager.') % values.get('state'))
|
||||||
result = super(Holidays, self).write(values)
|
result = super(Holidays, self).write(values)
|
||||||
self.add_follower(employee_id)
|
self.add_follower(employee_id)
|
||||||
|
if 'employee_id' in values:
|
||||||
|
self._onchange_employee_id()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
|
@ -85,6 +85,11 @@ class HrSalaryRuleCategory(models.Model):
|
|||||||
company_id = fields.Many2one('res.company', string='Company',
|
company_id = fields.Many2one('res.company', string='Company',
|
||||||
default=lambda self: self.env['res.company']._company_default_get())
|
default=lambda self: self.env['res.company']._company_default_get())
|
||||||
|
|
||||||
|
@api.constrains('parent_id')
|
||||||
|
def _check_parent_id(self):
|
||||||
|
if not self._check_recursion():
|
||||||
|
raise ValidationError(_('Error! You cannot create recursive hierarchy of Salary Rule Category.'))
|
||||||
|
|
||||||
|
|
||||||
class HrSalaryRule(models.Model):
|
class HrSalaryRule(models.Model):
|
||||||
_name = 'hr.salary.rule'
|
_name = 'hr.salary.rule'
|
||||||
@ -165,6 +170,11 @@ class HrSalaryRule(models.Model):
|
|||||||
input_ids = fields.One2many('hr.rule.input', 'input_id', string='Inputs', copy=True)
|
input_ids = fields.One2many('hr.rule.input', 'input_id', string='Inputs', copy=True)
|
||||||
note = fields.Text(string='Description')
|
note = fields.Text(string='Description')
|
||||||
|
|
||||||
|
@api.constrains('parent_rule_id')
|
||||||
|
def _check_parent_rule_id(self):
|
||||||
|
if not self._check_recursion(parent='parent_rule_id'):
|
||||||
|
raise ValidationError(_('Error! You cannot create recursive hierarchy of Salary Rules.'))
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _recursive_search_of_rules(self):
|
def _recursive_search_of_rules(self):
|
||||||
"""
|
"""
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
<record id="chart1181_en" model="account.account.template">
|
<record id="chart1181_en" model="account.account.template">
|
||||||
<field name="code">1181</field>
|
<field name="code">1181</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_current_liabilities"/>
|
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
|
||||||
<field name="reconcile" eval="False"/>
|
<field name="reconcile" eval="False"/>
|
||||||
<field name="name">GST receivable</field>
|
<field name="name">GST receivable</field>
|
||||||
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
||||||
@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
<record id="chart1182_en" model="account.account.template">
|
<record id="chart1182_en" model="account.account.template">
|
||||||
<field name="code">1182</field>
|
<field name="code">1182</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_current_liabilities"/>
|
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
|
||||||
<field name="reconcile" eval="False"/>
|
<field name="reconcile" eval="False"/>
|
||||||
<field name="name">PST/QST receivable</field>
|
<field name="name">PST/QST receivable</field>
|
||||||
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
||||||
@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
<record id="chart11831_en" model="account.account.template">
|
<record id="chart11831_en" model="account.account.template">
|
||||||
<field name="code">11831</field>
|
<field name="code">11831</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_current_liabilities"/>
|
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
|
||||||
<field name="reconcile" eval="False"/>
|
<field name="reconcile" eval="False"/>
|
||||||
<field name="name">HST receivable - 13%</field>
|
<field name="name">HST receivable - 13%</field>
|
||||||
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
||||||
@ -53,7 +53,7 @@
|
|||||||
|
|
||||||
<record id="chart11832_en" model="account.account.template">
|
<record id="chart11832_en" model="account.account.template">
|
||||||
<field name="code">11832</field>
|
<field name="code">11832</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_current_liabilities"/>
|
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
|
||||||
<field name="reconcile" eval="False"/>
|
<field name="reconcile" eval="False"/>
|
||||||
<field name="name">HST receivable - 14%</field>
|
<field name="name">HST receivable - 14%</field>
|
||||||
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
||||||
@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
<record id="chart11833_en" model="account.account.template">
|
<record id="chart11833_en" model="account.account.template">
|
||||||
<field name="code">11833</field>
|
<field name="code">11833</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_current_liabilities"/>
|
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
|
||||||
<field name="reconcile" eval="False"/>
|
<field name="reconcile" eval="False"/>
|
||||||
<field name="name">HST receivable - 15%</field>
|
<field name="name">HST receivable - 15%</field>
|
||||||
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
||||||
@ -79,7 +79,7 @@
|
|||||||
|
|
||||||
<record id="chart2131_en" model="account.account.template">
|
<record id="chart2131_en" model="account.account.template">
|
||||||
<field name="code">2131</field>
|
<field name="code">2131</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
|
<field name="user_type_id" ref="account.data_account_type_current_liabilities"/>
|
||||||
<field name="reconcile" eval="False"/>
|
<field name="reconcile" eval="False"/>
|
||||||
<field name="name">GST to pay</field>
|
<field name="name">GST to pay</field>
|
||||||
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
||||||
@ -87,7 +87,7 @@
|
|||||||
|
|
||||||
<record id="chart2132_en" model="account.account.template">
|
<record id="chart2132_en" model="account.account.template">
|
||||||
<field name="code">2132</field>
|
<field name="code">2132</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
|
<field name="user_type_id" ref="account.data_account_type_current_liabilities"/>
|
||||||
<field name="reconcile" eval="False"/>
|
<field name="reconcile" eval="False"/>
|
||||||
<field name="name">PST/QST to pay</field>
|
<field name="name">PST/QST to pay</field>
|
||||||
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
||||||
@ -95,7 +95,7 @@
|
|||||||
|
|
||||||
<record id="chart21331_en" model="account.account.template">
|
<record id="chart21331_en" model="account.account.template">
|
||||||
<field name="code">21331</field>
|
<field name="code">21331</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
|
<field name="user_type_id" ref="account.data_account_type_current_liabilities"/>
|
||||||
<field name="reconcile" eval="False"/>
|
<field name="reconcile" eval="False"/>
|
||||||
<field name="name">HST to pay - 13%</field>
|
<field name="name">HST to pay - 13%</field>
|
||||||
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
||||||
@ -103,7 +103,7 @@
|
|||||||
|
|
||||||
<record id="chart21332_en" model="account.account.template">
|
<record id="chart21332_en" model="account.account.template">
|
||||||
<field name="code">21332</field>
|
<field name="code">21332</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
|
<field name="user_type_id" ref="account.data_account_type_current_liabilities"/>
|
||||||
<field name="reconcile" eval="False"/>
|
<field name="reconcile" eval="False"/>
|
||||||
<field name="name">HST to pay - 14%</field>
|
<field name="name">HST to pay - 14%</field>
|
||||||
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
||||||
@ -111,7 +111,7 @@
|
|||||||
|
|
||||||
<record id="chart21333_en" model="account.account.template">
|
<record id="chart21333_en" model="account.account.template">
|
||||||
<field name="code">21333</field>
|
<field name="code">21333</field>
|
||||||
<field name="user_type_id" ref="account.data_account_type_current_assets"/>
|
<field name="user_type_id" ref="account.data_account_type_current_liabilities"/>
|
||||||
<field name="reconcile" eval="False"/>
|
<field name="reconcile" eval="False"/>
|
||||||
<field name="name">HST to pay - 15%</field>
|
<field name="name">HST to pay - 15%</field>
|
||||||
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
<field name="chart_template_id" ref="ca_en_chart_template_en"/>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<field name="cash_account_code_prefix">100</field>
|
<field name="cash_account_code_prefix">100</field>
|
||||||
<field name="currency_id" ref="base.CHF"/>
|
<field name="currency_id" ref="base.CHF"/>
|
||||||
<field name="transfer_account_id" ref="transfer_account_id"/>
|
<field name="transfer_account_id" ref="transfer_account_id"/>
|
||||||
<field name="spoken_languages" eval="'it_IT;de_CH'"/>
|
<field name="spoken_languages" eval="'it_IT;de_DE;de_CH'"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="transfer_account_id" model="account.account.template">
|
<record id="transfer_account_id" model="account.account.template">
|
||||||
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
<field name="chart_template_id" ref="l10nch_chart_template"/>
|
||||||
|
@ -149,6 +149,9 @@ class ProductProduct(models.Model):
|
|||||||
('barcode_uniq', 'unique(barcode)', "A barcode can only be assigned to one product !"),
|
('barcode_uniq', 'unique(barcode)', "A barcode can only be assigned to one product !"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def _get_invoice_policy(self):
|
||||||
|
return False
|
||||||
|
|
||||||
def _compute_product_price(self):
|
def _compute_product_price(self):
|
||||||
prices = {}
|
prices = {}
|
||||||
pricelist_id_or_name = self._context.get('pricelist')
|
pricelist_id_or_name = self._context.get('pricelist')
|
||||||
@ -219,6 +222,7 @@ class ProductProduct(models.Model):
|
|||||||
for supplier_info in self.seller_ids:
|
for supplier_info in self.seller_ids:
|
||||||
if supplier_info.name.id == self._context.get('partner_id'):
|
if supplier_info.name.id == self._context.get('partner_id'):
|
||||||
self.code = supplier_info.product_code or self.default_code
|
self.code = supplier_info.product_code or self.default_code
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
self.code = self.default_code
|
self.code = self.default_code
|
||||||
|
|
||||||
@ -227,9 +231,10 @@ class ProductProduct(models.Model):
|
|||||||
for supplier_info in self.seller_ids:
|
for supplier_info in self.seller_ids:
|
||||||
if supplier_info.name.id == self._context.get('partner_id'):
|
if supplier_info.name.id == self._context.get('partner_id'):
|
||||||
product_name = supplier_info.product_name or self.default_code
|
product_name = supplier_info.product_name or self.default_code
|
||||||
|
self.partner_ref = '%s%s' % (self.code and '[%s] ' % self.code or '', product_name)
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
product_name = self.name
|
self.partner_ref = self.name_get()[0][1]
|
||||||
self.partner_ref = '%s%s' % (self.code and '[%s] ' % self.code or '', product_name)
|
|
||||||
|
|
||||||
@api.one
|
@api.one
|
||||||
@api.depends('image_variant', 'product_tmpl_id.image')
|
@api.depends('image_variant', 'product_tmpl_id.image')
|
||||||
@ -428,7 +433,12 @@ class ProductProduct(models.Model):
|
|||||||
limit2 = (limit - len(products)) if limit else False
|
limit2 = (limit - len(products)) if limit else False
|
||||||
products += self.search(args + [('name', operator, name), ('id', 'not in', products.ids)], limit=limit2)
|
products += self.search(args + [('name', operator, name), ('id', 'not in', products.ids)], limit=limit2)
|
||||||
elif not products and operator in expression.NEGATIVE_TERM_OPERATORS:
|
elif not products and operator in expression.NEGATIVE_TERM_OPERATORS:
|
||||||
products = self.search(args + ['&', ('default_code', operator, name), ('name', operator, name)], limit=limit)
|
domain = expression.OR([
|
||||||
|
['&', ('default_code', operator, name), ('name', operator, name)],
|
||||||
|
['&', ('default_code', '=', False), ('name', operator, name)],
|
||||||
|
])
|
||||||
|
domain = expression.AND([args, domain])
|
||||||
|
products = self.search(domain, limit=limit)
|
||||||
if not products and operator in positive_operators:
|
if not products and operator in positive_operators:
|
||||||
ptrn = re.compile('(\[(.*?)\])')
|
ptrn = re.compile('(\[(.*?)\])')
|
||||||
res = ptrn.search(name)
|
res = ptrn.search(name)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
from flectra import api, fields, models, _
|
from flectra import api, fields, models, _
|
||||||
from flectra.addons import decimal_precision as dp
|
from flectra.addons import decimal_precision as dp
|
||||||
from flectra.exceptions import UserError, ValidationError
|
from flectra.exceptions import UserError, ValidationError
|
||||||
|
from flectra.osv import expression
|
||||||
|
|
||||||
|
|
||||||
class ProductAttribute(models.Model):
|
class ProductAttribute(models.Model):
|
||||||
@ -107,6 +108,6 @@ class ProductAttributeLine(models.Model):
|
|||||||
# search on a m2o and one on a m2m, probably this will quickly become
|
# search on a m2o and one on a m2m, probably this will quickly become
|
||||||
# difficult to compute - check if performance optimization is required
|
# difficult to compute - check if performance optimization is required
|
||||||
if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):
|
if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'):
|
||||||
args = ['|', ('attribute_id', operator, name), ('value_ids', operator, name)]
|
args = expression.AND([['|', ('attribute_id', operator, name), ('value_ids', operator, name)], args])
|
||||||
return self.search(args, limit=limit).name_get()
|
return self.search(args, limit=limit).name_get()
|
||||||
return super(ProductAttributeLine, self).name_search(name=name, args=args, operator=operator, limit=limit)
|
return super(ProductAttributeLine, self).name_search(name=name, args=args, operator=operator, limit=limit)
|
||||||
|
@ -45,6 +45,11 @@
|
|||||||
[<span t-esc="product.code"/>]
|
[<span t-esc="product.code"/>]
|
||||||
</t>
|
</t>
|
||||||
<span t-esc="product.name"/>
|
<span t-esc="product.name"/>
|
||||||
|
<span t-foreach="product.attribute_value_ids" t-as="attribute_value">
|
||||||
|
<span t-if="attribute_value_first">-</span>
|
||||||
|
<span t-if="not attribute_value_last" t-esc="attribute_value.name+','"/>
|
||||||
|
<span t-else="" t-esc="attribute_value.name"/>
|
||||||
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<t t-foreach="data['quantities']" t-as="quantity">
|
<t t-foreach="data['quantities']" t-as="quantity">
|
||||||
<td><strong t-esc="categ_data['prices'][product.id][quantity]"
|
<td><strong t-esc="categ_data['prices'][product.id][quantity]"
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr style="width: 1in;">
|
<tr style="width: 1in;">
|
||||||
<td style="border: 2px solid black;text-align: center; vertical-align: middle;" class="col-xs-5">
|
<td style="border: 2px solid black;text-align: center; vertical-align: middle;" class="col-xs-5">
|
||||||
<img t-if="product.barcode" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('EAN13', product.barcode, 600, 150)" style="width:100%;height:20%;"/>
|
<img t-if="product.barcode and len(product.barcode) == 13" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('EAN13', product.barcode, 600, 150)" style="width:100%;height:20%;"/>
|
||||||
|
<img t-elif="product.barcode and len(product.barcode) == 8" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('EAN8', product.barcode, 600, 150)" style="width:100%;height:20%;"/>
|
||||||
|
<img t-else="" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', product.barcode, 600, 150)" style="width:100%;height:20%;"/>
|
||||||
<span t-field="product.barcode"/>
|
<span t-field="product.barcode"/>
|
||||||
</td>
|
</td>
|
||||||
<td style="border: 2px solid black; text-align: center;" class="col-xs-7">
|
<td style="border: 2px solid black; text-align: center;" class="col-xs-7">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
from . import test_variants, test_uom, test_pricelist, test_product_pricelist
|
from . import test_seller, test_variants, test_uom, test_pricelist, test_product_pricelist
|
||||||
|
28
addons/product/tests/test_seller.py
Normal file
28
addons/product/tests/test_seller.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
from flectra.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestSeller(TransactionCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestSeller, self).setUp()
|
||||||
|
self.product_service = self.env.ref('product.product_product_2')
|
||||||
|
self.product_service.default_code = 'DEFCODE'
|
||||||
|
self.asustec = self.env.ref('base.res_partner_1')
|
||||||
|
self.camptocamp = self.env.ref('base.res_partner_12')
|
||||||
|
|
||||||
|
def test_10_sellers(self):
|
||||||
|
self.product_service.write({'seller_ids': [
|
||||||
|
(0, 0, {'name': self.asustec.id, 'product_code': 'ASUCODE'}),
|
||||||
|
(0, 0, {'name': self.camptocamp.id, 'product_code': 'C2CCODE'}),
|
||||||
|
]})
|
||||||
|
|
||||||
|
default_code = self.product_service.code
|
||||||
|
self.assertEqual("DEFCODE", default_code, "Default code not used in product name")
|
||||||
|
|
||||||
|
context_code = self.product_service\
|
||||||
|
.with_context(partner_id=self.camptocamp.id)\
|
||||||
|
.code
|
||||||
|
self.assertEqual('C2CCODE', context_code, "Partner's code not used in product name with context set")
|
@ -40,6 +40,15 @@ class TestVariantsSearch(TransactionCase):
|
|||||||
self.assertIn(self.product_shirt_template, search_value,
|
self.assertIn(self.product_shirt_template, search_value,
|
||||||
'Shirt should be found searching L')
|
'Shirt should be found searching L')
|
||||||
|
|
||||||
|
def test_name_search(self):
|
||||||
|
self.product_slip_template = self.env['product.template'].create({
|
||||||
|
'name': 'Slip',
|
||||||
|
})
|
||||||
|
res = self.env['product.product'].name_search('Shirt', [], 'not ilike', None)
|
||||||
|
res_ids = [r[0] for r in res]
|
||||||
|
self.assertIn(self.product_slip_template.product_variant_ids.id, res_ids,
|
||||||
|
'Slip should be found searching \'not ilike\'')
|
||||||
|
|
||||||
|
|
||||||
class TestVariants(common.TestProductCommon):
|
class TestVariants(common.TestProductCommon):
|
||||||
|
|
||||||
|
@ -90,6 +90,11 @@
|
|||||||
</group>
|
</group>
|
||||||
</page>
|
</page>
|
||||||
<page string="Notes" name="notes">
|
<page string="Notes" name="notes">
|
||||||
|
<group name="description_internal">
|
||||||
|
<group string="Description for Internal">
|
||||||
|
<field name="description" nolabel="1" placeholder="This note is only for internal purposes."/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
<group name="description">
|
<group name="description">
|
||||||
<group string="Description for Customers" attrs="{'invisible': [('sale_ok','=',False)]}">
|
<group string="Description for Customers" attrs="{'invisible': [('sale_ok','=',False)]}">
|
||||||
<field name="description_sale" nolabel="1" placeholder="This note will show up on sales orders."/>
|
<field name="description_sale" nolabel="1" placeholder="This note will show up on sales orders."/>
|
||||||
@ -202,7 +207,7 @@
|
|||||||
<field name="image_medium" widget="image" class="oe_avatar"/>
|
<field name="image_medium" widget="image" class="oe_avatar"/>
|
||||||
<div class="oe_title">
|
<div class="oe_title">
|
||||||
<label class="oe_edit_only" for="name" string="Product Name"/>
|
<label class="oe_edit_only" for="name" string="Product Name"/>
|
||||||
<h1><field name="name" placeholder="e.g. Flectra Enterprise Subscription"/></h1>
|
<h1><field name="name" placeholder="e.g. Flectra Subscription"/></h1>
|
||||||
</div>
|
</div>
|
||||||
<group>
|
<group>
|
||||||
<p>All general settings about this product are managed on <button name="open_product_template" type="object" string="the product template" class="oe_link"/></p>
|
<p>All general settings about this product are managed on <button name="open_product_template" type="object" string="the product template" class="oe_link"/></p>
|
||||||
|
@ -11,7 +11,8 @@
|
|||||||
<field name="name" invisible="1"/>
|
<field name="name" invisible="1"/>
|
||||||
<field name="model" invisible="1"/>
|
<field name="model" invisible="1"/>
|
||||||
<h3 colspan="2">Body</h3>
|
<h3 colspan="2">Body</h3>
|
||||||
<field name="body_html" nolabel="1" colspan="2" widget='text' />
|
<field name="body_html" nolabel="1" colspan="2" widget="html"
|
||||||
|
options="{'style-inline': true}" />
|
||||||
<field name="attachment_ids" nolabel="1" colspan="2"
|
<field name="attachment_ids" nolabel="1" colspan="2"
|
||||||
widget="many2many_binary"/>
|
widget="many2many_binary"/>
|
||||||
</group>
|
</group>
|
||||||
|
Loading…
Reference in New Issue
Block a user