diff --git a/addons/hr_payroll/models/hr_payroll.py b/addons/hr_payroll/models/hr_payroll.py
index 1de301eece7..8a5c5437196 100644
--- a/addons/hr_payroll/models/hr_payroll.py
+++ b/addons/hr_payroll/models/hr_payroll.py
@@ -579,21 +579,6 @@ class HrPayslip(models.Model):
})
return res
- # YTO TODO: employee_id and contract_id could be browse records
- @api.multi
- def onchange_contract_id(self, date_from, date_to, employee_id=False, contract_id=False):
- # TODO it seems to be the mess in the onchanges
- # we should have onchange_employee => onchange_contract => doing all the things
- res = {
- 'value': {
- 'line_ids': [],
- 'name': '',
- }
- }
- if not contract_id:
- res['value'].update({'struct_id': False})
- return self.with_context(contract=True).onchange_employee_id(date_from=date_from, date_to=date_to, employee_id=employee_id, contract_id=contract_id)
-
@api.onchange('employee_id', 'date_from')
def onchange_employee(self):
diff --git a/addons/hr_payroll_account/__init__.py b/addons/hr_payroll_account/__init__.py
index 44a09e23d48..ef00573b750 100644
--- a/addons/hr_payroll_account/__init__.py
+++ b/addons/hr_payroll_account/__init__.py
@@ -1,5 +1,5 @@
#-*- coding:utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import hr_payroll_account
+import models
import wizard
diff --git a/addons/hr_payroll_account/__openerp__.py b/addons/hr_payroll_account/__openerp__.py
index d3ab4701127..a7fc0604542 100644
--- a/addons/hr_payroll_account/__openerp__.py
+++ b/addons/hr_payroll_account/__openerp__.py
@@ -2,7 +2,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Payroll Accounting',
- 'version': '1.0',
'category': 'Human Resources',
'description': """
Generic Payroll system Integrated with Accounting.
@@ -12,14 +11,8 @@ Generic Payroll system Integrated with Accounting.
* Payment Encoding
* Company Contribution Management
""",
- 'depends': [
- 'hr_payroll',
- 'account',
- 'hr_expense'
- ],
- 'data': ['hr_payroll_account_view.xml'],
- 'demo': ['hr_payroll_account_demo.xml'],
- 'test': ['../account/test/account_minimal_test.xml', 'test/hr_payroll_account.yml'],
- 'installable': True,
- 'auto_install': False,
+ 'depends': ['hr_payroll', 'account', 'hr_expense'],
+ 'data': ['views/hr_payroll_account_views.xml'],
+ 'demo': ['data/hr_payroll_account_demo.xml'],
+ 'test': ['../account/test/account_minimal_test.xml'],
}
diff --git a/addons/hr_payroll_account/hr_payroll_account_demo.xml b/addons/hr_payroll_account/data/hr_payroll_account_demo.xml
similarity index 81%
rename from addons/hr_payroll_account/hr_payroll_account_demo.xml
rename to addons/hr_payroll_account/data/hr_payroll_account_demo.xml
index a8ac6414b94..6a4f3a9e39d 100644
--- a/addons/hr_payroll_account/hr_payroll_account_demo.xml
+++ b/addons/hr_payroll_account/data/hr_payroll_account_demo.xml
@@ -1,11 +1,6 @@
-
-
-
+
-
-
-
-
+
diff --git a/addons/hr_payroll_account/hr_payroll_account.py b/addons/hr_payroll_account/hr_payroll_account.py
deleted file mode 100644
index a9871453885..00000000000
--- a/addons/hr_payroll_account/hr_payroll_account.py
+++ /dev/null
@@ -1,222 +0,0 @@
-#-*- coding:utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import time
-from datetime import date, datetime, timedelta
-
-from openerp import api
-from openerp.osv import fields, osv
-from openerp.tools import float_compare, float_is_zero
-from openerp.tools.translate import _
-from openerp.exceptions import UserError
-
-class hr_payslip_line(osv.osv):
- '''
- Payslip Line
- '''
- _inherit = 'hr.payslip.line'
-
- def _get_partner_id(self, cr, uid, payslip_line, credit_account, context=None):
- """
- Get partner_id of slip line to use in account_move_line
- """
- # use partner of salary rule or fallback on employee's address
- partner_id = payslip_line.salary_rule_id.register_id.partner_id.id or \
- payslip_line.slip_id.employee_id.address_home_id.id
- if credit_account:
- if payslip_line.salary_rule_id.register_id.partner_id or \
- payslip_line.salary_rule_id.account_credit.internal_type in ('receivable', 'payable'):
- return partner_id
- else:
- if payslip_line.salary_rule_id.register_id.partner_id or \
- payslip_line.salary_rule_id.account_debit.internal_type in ('receivable', 'payable'):
- return partner_id
- return False
-
-
-class hr_payslip(osv.osv):
- '''
- Pay Slip
- '''
- _inherit = 'hr.payslip'
- _description = 'Pay Slip'
-
- _columns = {
- 'date': fields.date('Date Account', states={'draft': [('readonly', False)]}, readonly=True, help="Keep empty to use the period of the validation(Payslip) date."),
- 'journal_id': fields.many2one('account.journal', 'Salary Journal',states={'draft': [('readonly', False)]}, readonly=True, required=True),
- 'move_id': fields.many2one('account.move', 'Accounting Entry', readonly=True, copy=False),
- }
-
- def _get_default_journal(self, cr, uid, context=None):
- journal_obj = self.pool.get('account.journal')
- res = journal_obj.search(cr, uid, [('type', '=', 'general')])
- if res:
- return res[0]
- return False
-
- _defaults = {
- 'journal_id': _get_default_journal,
- }
-
- def create(self, cr, uid, vals, context=None):
- if context is None:
- context = {}
- if 'journal_id' in context:
- vals.update({'journal_id': context.get('journal_id')})
- return super(hr_payslip, self).create(cr, uid, vals, context=context)
-
- def onchange_contract_id(self, cr, uid, ids, date_from, date_to, employee_id=False, contract_id=False, context=None):
- contract_obj = self.pool.get('hr.contract')
- res = super(hr_payslip, self).onchange_contract_id(cr, uid, ids, date_from=date_from, date_to=date_to, employee_id=employee_id, contract_id=contract_id, context=context)
- journal_id = contract_id and contract_obj.browse(cr, uid, contract_id, context=context).journal_id.id or (not contract_id and self._get_default_journal(cr, uid, context=None))
- res['value'].update({'journal_id': journal_id})
- return res
-
- @api.onchange('contract_id')
- def onchange_contract(self):
- super(hr_payslip, self).onchange_contract()
- self.journal_id = self.contract_id and self.contract_id.journal_id.id or (not self.contract_id and self._get_default_journal())
- return
-
- def cancel_sheet(self, cr, uid, ids, context=None):
- move_pool = self.pool.get('account.move')
- move_ids = []
- move_to_cancel = []
- for slip in self.browse(cr, uid, ids, context=context):
- if slip.move_id:
- move_ids.append(slip.move_id.id)
- if slip.move_id.state == 'posted':
- move_to_cancel.append(slip.move_id.id)
- move_pool.button_cancel(cr, uid, move_to_cancel, context=context)
- move_pool.unlink(cr, uid, move_ids, context=context)
- return super(hr_payslip, self).cancel_sheet(cr, uid, ids, context=context)
-
- def process_sheet(self, cr, uid, ids, context=None):
- move_pool = self.pool.get('account.move')
- hr_payslip_line_pool = self.pool['hr.payslip.line']
- precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Payroll')
- timenow = time.strftime('%Y-%m-%d')
-
- for slip in self.browse(cr, uid, ids, context=context):
- line_ids = []
- debit_sum = 0.0
- credit_sum = 0.0
- date = timenow
-
- name = _('Payslip of %s') % (slip.employee_id.name)
- move = {
- 'narration': name,
- 'ref': slip.number,
- 'journal_id': slip.journal_id.id,
- 'date': date,
- }
- for line in slip.details_by_salary_rule_category:
- amt = slip.credit_note and -line.total or line.total
- if float_is_zero(amt, precision_digits=precision):
- continue
- debit_account_id = line.salary_rule_id.account_debit.id
- credit_account_id = line.salary_rule_id.account_credit.id
-
- if debit_account_id:
- debit_line = (0, 0, {
- 'name': line.name,
- 'partner_id': hr_payslip_line_pool._get_partner_id(cr, uid, line, credit_account=False, context=context),
- 'account_id': debit_account_id,
- 'journal_id': slip.journal_id.id,
- 'date': date,
- 'debit': amt > 0.0 and amt or 0.0,
- 'credit': amt < 0.0 and -amt or 0.0,
- 'analytic_account_id': line.salary_rule_id.analytic_account_id and line.salary_rule_id.analytic_account_id.id or False,
- 'tax_line_id': line.salary_rule_id.account_tax_id and line.salary_rule_id.account_tax_id.id or False,
- })
- line_ids.append(debit_line)
- debit_sum += debit_line[2]['debit'] - debit_line[2]['credit']
-
- if credit_account_id:
- credit_line = (0, 0, {
- 'name': line.name,
- 'partner_id': hr_payslip_line_pool._get_partner_id(cr, uid, line, credit_account=True, context=context),
- 'account_id': credit_account_id,
- 'journal_id': slip.journal_id.id,
- 'date': date,
- 'debit': amt < 0.0 and -amt or 0.0,
- 'credit': amt > 0.0 and amt or 0.0,
- 'analytic_account_id': line.salary_rule_id.analytic_account_id and line.salary_rule_id.analytic_account_id.id or False,
- 'tax_line_id': line.salary_rule_id.account_tax_id and line.salary_rule_id.account_tax_id.id or False,
- })
- line_ids.append(credit_line)
- credit_sum += credit_line[2]['credit'] - credit_line[2]['debit']
-
- if float_compare(credit_sum, debit_sum, precision_digits=precision) == -1:
- acc_id = slip.journal_id.default_credit_account_id.id
- if not acc_id:
- raise UserError(_('The Expense Journal "%s" has not properly configured the Credit Account!') % (slip.journal_id.name))
- adjust_credit = (0, 0, {
- 'name': _('Adjustment Entry'),
- 'date': timenow,
- 'partner_id': False,
- 'account_id': acc_id,
- 'journal_id': slip.journal_id.id,
- 'date': date,
- 'debit': 0.0,
- 'credit': debit_sum - credit_sum,
- })
- line_ids.append(adjust_credit)
-
- elif float_compare(debit_sum, credit_sum, precision_digits=precision) == -1:
- acc_id = slip.journal_id.default_debit_account_id.id
- if not acc_id:
- raise UserError(_('The Expense Journal "%s" has not properly configured the Debit Account!') % (slip.journal_id.name))
- adjust_debit = (0, 0, {
- 'name': _('Adjustment Entry'),
- 'partner_id': False,
- 'account_id': acc_id,
- 'journal_id': slip.journal_id.id,
- 'date': date,
- 'debit': credit_sum - debit_sum,
- 'credit': 0.0,
- })
- line_ids.append(adjust_debit)
-
- move.update({'line_ids': line_ids})
- move_id = move_pool.create(cr, uid, move, context=context)
- self.write(cr, uid, [slip.id], {'move_id': move_id, 'date' : date}, context=context)
- move_pool.post(cr, uid, [move_id], context=context)
- return super(hr_payslip, self).process_sheet(cr, uid, [slip.id], context=context)
-
-
-class hr_salary_rule(osv.osv):
- _inherit = 'hr.salary.rule'
- _columns = {
- 'analytic_account_id':fields.many2one('account.analytic.account', 'Analytic Account'),
- 'account_tax_id':fields.many2one('account.tax', 'Tax'),
- 'account_debit': fields.many2one('account.account', 'Debit Account', domain=[('deprecated', '=', False)]),
- 'account_credit': fields.many2one('account.account', 'Credit Account', domain=[('deprecated', '=', False)]),
- }
-
-class hr_contract(osv.osv):
-
- _inherit = 'hr.contract'
- _description = 'Employee Contract'
- _columns = {
- 'analytic_account_id':fields.many2one('account.analytic.account', 'Analytic Account'),
- 'journal_id': fields.many2one('account.journal', 'Salary Journal'),
- }
-
-class hr_payslip_run(osv.osv):
-
- _inherit = 'hr.payslip.run'
- _description = 'Payslip Run'
- _columns = {
- 'journal_id': fields.many2one('account.journal', 'Salary Journal', states={'draft': [('readonly', False)]}, readonly=True, required=True),
- }
-
- def _get_default_journal(self, cr, uid, context=None):
- journal_obj = self.pool.get('account.journal')
- res = journal_obj.search(cr, uid, [('type', '=', 'general')])
- if res:
- return res[0]
- return False
-
- _defaults = {
- 'journal_id': _get_default_journal,
- }
diff --git a/addons/hr_payroll_account/models/__init__.py b/addons/hr_payroll_account/models/__init__.py
new file mode 100644
index 00000000000..df42a35e812
--- /dev/null
+++ b/addons/hr_payroll_account/models/__init__.py
@@ -0,0 +1,4 @@
+#-*- coding:utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import hr_payroll_account
\ No newline at end of file
diff --git a/addons/hr_payroll_account/models/hr_payroll_account.py b/addons/hr_payroll_account/models/hr_payroll_account.py
new file mode 100644
index 00000000000..2501a10ce7e
--- /dev/null
+++ b/addons/hr_payroll_account/models/hr_payroll_account.py
@@ -0,0 +1,165 @@
+#-*- coding:utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import api, fields, models, _
+from odoo.exceptions import UserError
+from odoo.tools import float_compare, float_is_zero
+
+
+class HrPayslipLine(models.Model):
+ _inherit = 'hr.payslip.line'
+
+ def _get_partner_id(self, credit_account):
+ """
+ Get partner_id of slip line to use in account_move_line
+ """
+ # use partner of salary rule or fallback on employee's address
+ register_partner_id = self.salary_rule_id.register_id.partner_id
+ partner_id = register_partner_id.id or self.slip_id.employee_id.address_home_id.id
+ if credit_account:
+ if register_partner_id or self.salary_rule_id.account_credit.internal_type in ('receivable', 'payable'):
+ return partner_id
+ else:
+ if register_partner_id or self.salary_rule_id.account_debit.internal_type in ('receivable', 'payable'):
+ return partner_id
+ return False
+
+class HrPayslip(models.Model):
+ _inherit = 'hr.payslip'
+
+ date = fields.Date('Date Account', states={'draft': [('readonly', False)]}, readonly=True,
+ help="Keep empty to use the period of the validation(Payslip) date.")
+ journal_id = fields.Many2one('account.journal', 'Salary Journal', readonly=True, required=True,
+ states={'draft': [('readonly', False)]}, default=lambda self: self.env['account.journal'].search([('type', '=', 'general')], limit=1))
+ move_id = fields.Many2one('account.move', 'Accounting Entry', readonly=True, copy=False)
+
+ @api.model
+ def create(self, vals):
+ if 'journal_id' in self.env.context:
+ vals['journal_id'] = self.env.context.get('journal_id')
+ return super(HrPayslip, self).create(vals)
+
+ @api.onchange('contract_id')
+ def onchange_contract(self):
+ super(HrPayslip, self).onchange_contract()
+ self.journal_id = self.contract_id.journal_id.id or (not self.contract_id and self.default_get(['journal_id'])['journal_id'])
+
+ @api.multi
+ def cancel_sheet(self):
+ moves = self.mapped('move_id')
+ moves.filtered(lambda x: x.state == 'posted').button_cancel()
+ moves.unlink()
+ return super(HrPayslip, self).cancel_sheet()
+
+ @api.multi
+ def process_sheet(self):
+ precision = self.env['decimal.precision'].precision_get('Payroll')
+ today = fields.Date.today()
+
+ for slip in self:
+ line_ids = []
+ debit_sum = 0.0
+ credit_sum = 0.0
+
+ name = _('Payslip of %s') % (slip.employee_id.name)
+ move_dict = {
+ 'narration': name,
+ 'ref': slip.number,
+ 'journal_id': slip.journal_id.id,
+ 'date': today,
+ }
+ for line in slip.details_by_salary_rule_category:
+ amount = slip.credit_note and -line.total or line.total
+ if float_is_zero(amount, precision_digits=precision):
+ continue
+ debit_account_id = line.salary_rule_id.account_debit.id
+ credit_account_id = line.salary_rule_id.account_credit.id
+
+ if debit_account_id:
+ debit_line = (0, 0, {
+ 'name': line.name,
+ 'partner_id': line._get_partner_id(credit_account=False),
+ 'account_id': debit_account_id,
+ 'journal_id': slip.journal_id.id,
+ 'date': today,
+ 'debit': amount > 0.0 and amount or 0.0,
+ 'credit': amount < 0.0 and -amount or 0.0,
+ 'analytic_account_id': line.salary_rule_id.analytic_account_id.id,
+ 'tax_line_id': line.salary_rule_id.account_tax_id.id,
+ })
+ line_ids.append(debit_line)
+ debit_sum += debit_line[2]['debit'] - debit_line[2]['credit']
+
+ if credit_account_id:
+ credit_line = (0, 0, {
+ 'name': line.name,
+ 'partner_id': line._get_partner_id(credit_account=True),
+ 'account_id': credit_account_id,
+ 'journal_id': slip.journal_id.id,
+ 'date': today,
+ 'debit': amount < 0.0 and -amount or 0.0,
+ 'credit': amount > 0.0 and amount or 0.0,
+ 'analytic_account_id': line.salary_rule_id.analytic_account_id.id,
+ 'tax_line_id': line.salary_rule_id.account_tax_id.id,
+ })
+ line_ids.append(credit_line)
+ credit_sum += credit_line[2]['credit'] - credit_line[2]['debit']
+
+ if float_compare(credit_sum, debit_sum, precision_digits=precision) == -1:
+ acc_id = slip.journal_id.default_credit_account_id.id
+ if not acc_id:
+ raise UserError(_('The Expense Journal "%s" has not properly configured the Credit Account!') % (slip.journal_id.name))
+ adjust_credit = (0, 0, {
+ 'name': _('Adjustment Entry'),
+ 'date': today,
+ 'partner_id': False,
+ 'account_id': acc_id,
+ 'journal_id': slip.journal_id.id,
+ 'date': today,
+ 'debit': 0.0,
+ 'credit': debit_sum - credit_sum,
+ })
+ line_ids.append(adjust_credit)
+
+ elif float_compare(debit_sum, credit_sum, precision_digits=precision) == -1:
+ acc_id = slip.journal_id.default_debit_account_id.id
+ if not acc_id:
+ raise UserError(_('The Expense Journal "%s" has not properly configured the Debit Account!') % (slip.journal_id.name))
+ adjust_debit = (0, 0, {
+ 'name': _('Adjustment Entry'),
+ 'partner_id': False,
+ 'account_id': acc_id,
+ 'journal_id': slip.journal_id.id,
+ 'date': today,
+ 'debit': credit_sum - debit_sum,
+ 'credit': 0.0,
+ })
+ line_ids.append(adjust_debit)
+ move_dict['line_ids'] = line_ids
+ move = self.env['account.move'].create(move_dict)
+ slip.write({'move_id': move.id, 'date': today})
+ move.post()
+ return super(HrPayslip, self).process_sheet()
+
+
+class HrSalaryRule(models.Model):
+ _inherit = 'hr.salary.rule'
+
+ analytic_account_id = fields.Many2one('account.analytic.account', 'Analytic Account')
+ account_tax_id = fields.Many2one('account.tax', 'Tax')
+ account_debit = fields.Many2one('account.account', 'Debit Account', domain=[('deprecated', '=', False)])
+ account_credit = fields.Many2one('account.account', 'Credit Account', domain=[('deprecated', '=', False)])
+
+class HrContract(models.Model):
+ _inherit = 'hr.contract'
+ _description = 'Employee Contract'
+
+ analytic_account_id = fields.Many2one('account.analytic.account', 'Analytic Account')
+ journal_id = fields.Many2one('account.journal', 'Salary Journal')
+
+class HrPayslipRun(models.Model):
+ _inherit = 'hr.payslip.run'
+ _description = 'Payslip Run'
+
+ journal_id = fields.Many2one('account.journal', 'Salary Journal', states={'draft': [('readonly', False)]}, readonly=True,
+ required=True, default=lambda self: self.env['account.journal'].search([('type', '=', 'general')], limit=1))
diff --git a/addons/hr_payroll_account/test/hr_payroll_account.yml b/addons/hr_payroll_account/test/hr_payroll_account.yml
deleted file mode 100644
index fc4e81c4ac5..00000000000
--- a/addons/hr_payroll_account/test/hr_payroll_account.yml
+++ /dev/null
@@ -1,124 +0,0 @@
--
- I test the "Payslip" in order to check the hr_payroll_account module in OpenERP.
--
- I create a bank record.
--
- !record {model: res.partner.bank, id: res_partner_bank_0}:
- acc_number: '001-9876543-21'
- partner_id: base.res_partner_12
- acc_type: bank
- bank_id: base.res_bank_1
--
- I create a new employee "John".
--
- !record {model: hr.employee, id: hr_employee_john}:
- address_home_id: base.res_partner_address_2
- address_id: base.res_partner_address_12
- birthday: '1984-05-01'
- children: 0.0
- country_id: base.in
- department_id: hr.dep_rd
- gender: male
- marital: single
- name: John
- bank_account_id: res_partner_bank_0
- vehicle_distance: 0.0
--
- I create a salary structure for 'Software Developer'.
--
- !record {model: hr.payroll.structure, id: hr_payroll_structure_softwaredeveloper}:
- name: Salary Structure for Software Developer
- code: SD
- company_id: base.main_company
- parent_id: hr_payroll.structure_base
- rule_ids:
- - hr_payroll.hr_salary_rule_houserentallowance1
- - hr_payroll.hr_salary_rule_convanceallowance1
- - hr_payroll.hr_salary_rule_professionaltax1
- - hr_payroll.hr_salary_rule_providentfund1
- - hr_payroll.hr_salary_rule_meal_voucher
- - hr_payroll.hr_salary_rule_sales_commission
--
- I create a contract for "John".
--
- !record {model: hr.contract, id: hr_contract_john}:
- date_end: !eval "(datetime.now() + timedelta(days=365)).strftime('%Y-%m-%d')"
- date_start: !eval time.strftime('%Y-%m-%d')
- name: Contract for John
- wage: 5000.0
- type_id: hr_contract.hr_contract_type_emp
- employee_id: hr_employee_john
- struct_id: hr_payroll_structure_softwaredeveloper
- working_hours: resource.timesheet_group1
- journal_id: expenses_journal
--
- I create a Payslip.
--
- !record {model: hr.payslip, id: hr_payslip_0}:
- employee_id: hr_employee_john
- journal_id: expenses_journal
-
--
- The selection of an employee fills the contract, structure, worked days and input data fields.
--
- !python {model: hr.payslip}: |
- import time
- from datetime import datetime
- from dateutil import relativedelta
- date_from = time.strftime('%Y-%m-01')
- worked_days_obj = self.pool.get('hr.payslip.worked_days')
- date_to = str(datetime.now() + relativedelta.relativedelta(months=+1, day=1, days=-1))[:10]
- res = self.onchange_employee_id(cr, uid, [], date_from, date_to, ref("hr_employee_john"), False, None)
- vals = {
- 'struct_id': res['value']['struct_id'],
- 'contract_id': res['value']['contract_id'],
- 'name': res['value']['name'],
- }
- vals['worked_days_line_ids'] = [(0,0,i) for i in res['value']['worked_days_line_ids']]
- vals['input_line_ids'] = [(0,0,i) for i in res['value']['input_line_ids']]
- res_contract = self.onchange_contract_id(cr, uid, [ref('hr_payslip_0')], date_from, date_to, ref('hr_employee_john'), ref('hr_contract_john'), None)
- vals.update({'contract_id': ref('hr_contract_john')})
- self.write(cr, uid, ref("hr_payslip_0"), vals)
--
- I assign the amount to Input data.
--
- !python {model: hr.payslip.input}: |
- ids = self.search(cr, uid, [('payslip_id', '=', ref("hr_payslip_0"))])
- self.write(cr, uid, ids, {'amount': 5.0})
--
- I verify the payslip is in draft state.
--
- !python {model: hr.payslip}: |
- payslip_brw=self.browse(cr, uid, ref("hr_payslip_0"))
- assert(payslip_brw.state == 'draft'), 'State not changed!'
--
- I click on "Compute Sheet" button.
--
- !python {model: hr.payslip}: |
- self.compute_sheet(cr, uid, [ref("hr_payslip_0")], {"lang": "en_US", "tz": False,
- "active_model": "ir.ui.menu", "department_id": False, "active_ids": [ref("hr_payroll.menu_department_tree")],
- "section_id": False, "active_id": ref("hr_payroll.menu_department_tree"),
- })
--
- I want to check cancel button. So I first cancel the sheet then make it set to draft.
--
- !python {model: hr.payslip}: |
- self.cancel_sheet(cr, uid, [ref("hr_payslip_0")], None)
- self.signal_workflow(cr, uid, [ref("hr_payslip_0")], 'draft')
--
- Then I click on the "Confirm" button.
--
- !workflow {model: hr.payslip, action: hr_verify_sheet, ref: hr_payslip_0}
--
- I verify that the Accounting Entries are created.
--
- !python {model: hr.payslip}: |
- payslip = self.browse(cr, uid, ref("hr_payslip_0"))
- assert payslip.move_id, "Accounting Entries has not been created"
--
- I verify that the payslip is in done state.
--
- !python {model: hr.payslip}: |
- payslip_brw=self.browse(cr, uid, ref("hr_payslip_0"))
- assert(payslip_brw.state == 'done'), 'State not changed!'
-
diff --git a/addons/hr_payroll_account/tests/__init__.py b/addons/hr_payroll_account/tests/__init__.py
new file mode 100644
index 00000000000..fddb4dff262
--- /dev/null
+++ b/addons/hr_payroll_account/tests/__init__.py
@@ -0,0 +1,4 @@
+#-*- coding:utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import test_hr_payroll_account
\ No newline at end of file
diff --git a/addons/hr_payroll_account/tests/test_hr_payroll_account.py b/addons/hr_payroll_account/tests/test_hr_payroll_account.py
new file mode 100644
index 00000000000..759c4c51a43
--- /dev/null
+++ b/addons/hr_payroll_account/tests/test_hr_payroll_account.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import time
+
+from datetime import datetime, timedelta
+from dateutil import relativedelta
+from odoo import fields, tools
+
+from openerp.addons.account.tests.account_test_classes import AccountingTestCase
+from odoo.modules.module import get_module_resource
+from odoo.tests import common
+
+
+class TestHrPayrollAccount(common.TransactionCase):
+
+ def _load(self, module, *args):
+ tools.convert_file(self.cr, 'hr_payroll_account',
+ get_module_resource(module, *args), {}, 'init', False, 'test', self.registry._assertion_report)
+
+ def setUp(self):
+ super(TestHrPayrollAccount, self).setUp()
+
+ self._load('account', 'test', 'account_minimal_test.xml')
+
+ self.payslip_action_id = self.ref('hr_payroll.menu_department_tree')
+
+ self.res_partner_bank = self.env['res.partner.bank'].create({
+ 'acc_number': '001-9876543-21',
+ 'partner_id': self.ref('base.res_partner_12'),
+ 'acc_type': 'bank',
+ 'bank_id': self.ref('base.res_bank_1'),
+ })
+
+ self.hr_employee_john = self.env['hr.employee'].create({
+ 'address_home_id': self.ref('base.res_partner_address_2'),
+ 'address_id': self.ref('base.res_partner_address_12'),
+ 'birthday': '1984-05-01',
+ 'children': 0.0,
+ 'country_id': self.ref('base.in'),
+ 'department_id': self.ref('hr.dep_rd'),
+ 'gender': 'male',
+ 'marital': 'single',
+ 'name': 'John',
+ 'bank_account_id': self.res_partner_bank.bank_id.id,
+ 'vehicle_distance': 0.0,
+ })
+
+ self.hr_structure_softwaredeveloper = self.env['hr.payroll.structure'].create({
+ 'name': 'Salary Structure for Software Developer',
+ 'code': 'SD',
+ 'company_id': self.ref('base.main_company'),
+ 'parent_id': self.ref('hr_payroll.structure_base'),
+ 'rule_ids': [(6, 0, [
+ self.ref('hr_payroll.hr_salary_rule_houserentallowance1'),
+ self.ref('hr_payroll.hr_salary_rule_convanceallowance1'),
+ self.ref('hr_payroll.hr_salary_rule_professionaltax1'),
+ self.ref('hr_payroll.hr_salary_rule_providentfund1'),
+ self.ref('hr_payroll.hr_salary_rule_meal_voucher'),
+ self.ref('hr_payroll.hr_salary_rule_sales_commission')
+ ])],
+ })
+
+ # Create account journal.
+ self.hr_contract_john = self.env['hr.contract'].create({
+ 'date_end': fields.Date.to_string(datetime.now() + timedelta(days=365)),
+ 'date_start': fields.Date.today(),
+ 'name': 'Contract for John',
+ 'wage': 5000.0,
+ 'type_id': self.ref('hr_contract.hr_contract_type_emp'),
+ 'employee_id': self.hr_employee_john.id,
+ 'struct_id': self.hr_structure_softwaredeveloper.id,
+ 'working_hours': self.ref('resource.timesheet_group1'),
+ 'journal_id': self.ref('hr_payroll_account.expenses_journal'),
+ })
+
+ self.hr_payslip = self.env['hr.payslip'].create({
+ 'employee_id': self.hr_employee_john.id,
+ 'journal_id': self.ref('hr_payroll_account.expenses_journal'),
+ })
+
+ def test_00_hr_payslip(self):
+ """ checking the process of payslip. """
+
+ date_from = time.strftime('%Y-%m-01')
+ date_to = str(datetime.now() + relativedelta.relativedelta(months=+1, day=1, days=-1))[:10]
+ res = self.hr_payslip.onchange_employee_id(date_from, date_to, self.hr_employee_john.id)
+ vals = {
+ 'struct_id': res['value']['struct_id'],
+ 'contract_id': res['value']['contract_id'],
+ 'name': res['value']['name'],
+ }
+ vals['worked_days_line_ids'] = [(0, 0, i) for i in res['value']['worked_days_line_ids']]
+ vals['input_line_ids'] = [(0, 0, i) for i in res['value']['input_line_ids']]
+ vals.update({'contract_id': self.hr_contract_john.id})
+ self.hr_payslip.write(vals)
+
+ # I assign the amount to Input data.
+ payslip_input = self.env['hr.payslip.input'].search([('payslip_id', '=', self.hr_payslip.id)])
+ payslip_input.write({'amount': 5.0})
+
+ # I verify the payslip is in draft state.
+ self.assertEqual(self.hr_payslip.state, 'draft', 'State not changed!')
+
+ # I click on "Compute Sheet" button.
+ context = {"lang": "en_US", "tz": False, "active_model": 'hr.payslip', "department_id": False, "active_ids": [self.payslip_action_id], "section_id": False, "active_id": self.payslip_action_id}
+ self.hr_payslip.with_context(context).compute_sheet()
+
+ # I want to check cancel button. So I first cancel the sheet then make it set to draft.
+ self.hr_payslip.cancel_sheet()
+ self.assertEqual(self.hr_payslip.state, 'cancel', "Payslip is rejected.")
+ self.hr_payslip.signal_workflow('draft')
+
+ # Confirm Payslip
+ self.hr_payslip.signal_workflow('hr_verify_sheet')
+
+ # I verify that the Accounting Entries are created.
+ self.assertTrue(self.hr_payslip.move_id, 'Accounting Entries has not been created')
+
+ # I verify that the payslip is in done state.
+ self.assertEqual(self.hr_payslip.state, 'done', 'State not changed!')
diff --git a/addons/hr_payroll_account/hr_payroll_account_view.xml b/addons/hr_payroll_account/views/hr_payroll_account_views.xml
similarity index 98%
rename from addons/hr_payroll_account/hr_payroll_account_view.xml
rename to addons/hr_payroll_account/views/hr_payroll_account_views.xml
index 618261b54f8..9617c903395 100644
--- a/addons/hr_payroll_account/hr_payroll_account_view.xml
+++ b/addons/hr_payroll_account/views/hr_payroll_account_views.xml
@@ -1,7 +1,5 @@
-
-
-
-
+
+
hr.payslip.inherit.form
hr.payslip
@@ -85,6 +83,4 @@
-
-
-
+
diff --git a/addons/hr_payroll_account/wizard/hr_payroll_payslips_by_employees.py b/addons/hr_payroll_account/wizard/hr_payroll_payslips_by_employees.py
index 4e37ddd0f1c..5da19c2c361 100644
--- a/addons/hr_payroll_account/wizard/hr_payroll_payslips_by_employees.py
+++ b/addons/hr_payroll_account/wizard/hr_payroll_payslips_by_employees.py
@@ -1,20 +1,14 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from openerp.osv import osv
+from odoo import api, models
-class hr_payslip_employees(osv.osv_memory):
+class HrPayslipEmployees(models.TransientModel):
+ _inherit = 'hr.payslip.employees'
- _inherit ='hr.payslip.employees'
-
- def compute_sheet(self, cr, uid, ids, context=None):
- run_pool = self.pool.get('hr.payslip.run')
- if context is None:
- context = {}
- if context.get('active_id'):
- run_data = run_pool.read(cr, uid, context['active_id'], ['journal_id'])
- journal_id = run_data.get('journal_id')
- journal_id = journal_id and journal_id[0] or False
- if journal_id:
- context = dict(context, journal_id=journal_id)
- return super(hr_payslip_employees, self).compute_sheet(cr, uid, ids, context=context)
+ @api.multi
+ def compute_sheet(self):
+ journal_id = False
+ if self.env.context.get('active_id'):
+ journal_id = self.env['hr.payslip.run'].browse(self.env.context.get['active_id']).journal_id.id
+ return super(HrPayslipEmployees, self).with_context(journal_id=journal_id).compute_sheet()