[IMP] hr_payroll: Add a multi-report printing mechanism

Purpose
=======

We can't have only one report template for all the payslips. Some things
are specific to belgium, or another country. (For example, display the
amount on meal vouchers on the payslip). We should add an multi action,
and a button on the payslip form to print it.

Add a report field on a salary structure. This report is used on printing.

That way we can specify another report for a given salary structure and
print all the document of a employee with the correct report on each
payslip.

closes odoo/odoo#29674
This commit is contained in:
jbm-odoo
2019-01-03 10:12:36 +00:00
committed by Yannick Tivisse
parent 3e9102bb50
commit dbf7257971
11 changed files with 129 additions and 2 deletions
+1
View File
@@ -4,3 +4,4 @@
from . import models
from . import report
from . import wizard
from . import controllers
+3
View File
@@ -35,4 +35,7 @@
'wizard/hr_benefit_employee_views.xml',
],
'demo': ['data/hr_payroll_demo.xml'],
'qweb': [
"static/src/xml/payslip_tree_views.xml",
],
}
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import main
+50
View File
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import io
import re
from PyPDF2 import PdfFileReader, PdfFileWriter
from odoo.http import request, route, Controller
from odoo.tools.safe_eval import safe_eval
class HrPayroll(Controller):
@route(["/print/payslips"], type='http', auth='user')
def get_payroll_report_print(self, list_ids='', **post):
if not request.env.user.has_group('hr_payroll.group_hr_payroll_user') or not list_ids or re.search("[^0-9|,]", list_ids):
return request.not_found()
ids = [int(s) for s in list_ids.split(',')]
payslips = request.env['hr.payslip'].browse(ids)
pdf_writer = PdfFileWriter()
for payslip in payslips:
if not payslip.struct_id or not payslip.struct_id.report_id:
continue
pdf_content, _ = payslip.struct_id.report_id.render_qweb_pdf(payslip.id)
reader = PdfFileReader(io.BytesIO(pdf_content), strict=False, overwriteWarnings=False)
for page in range(reader.getNumPages()):
pdf_writer.addPage(reader.getPage(page))
_buffer = io.BytesIO()
pdf_writer.write(_buffer)
merged_pdf = _buffer.getvalue()
_buffer.close()
if len(payslips) == 1 and payslips.struct_id.report_id.print_report_name:
report_name = safe_eval(payslips.struct_id.report_id.print_report_name, {'object': payslips})
else:
report_name = "Payslips"
pdfhttpheaders = [
('Content-Type', 'application/pdf'),
('Content-Length', len(merged_pdf)),
('Content-Disposition', 'attachment; filename=' + report_name + '.pdf;')
]
return request.make_response(merged_pdf, headers=pdfhttpheaders)
+8
View File
@@ -311,6 +311,14 @@ class HrPayslip(models.Model):
else:
return 0.0
@api.multi
def action_print_payslip(self):
return {
'name': 'Payslip',
'type': 'ir.actions.act_url',
'url': '/print/payslips?list_ids=%(list_ids)s' % {'list_ids': ','.join(str(x) for x in self.ids)},
}
class HrPayslipLine(models.Model):
_name = 'hr.payslip.line'
@@ -21,6 +21,10 @@ class HrPayrollStructure(models.Model):
def _get_parent(self):
return self.env.ref('hr_payroll.structure_base', False)
@api.model
def _get_default_report_id(self):
return self.env.ref('hr_payroll.action_report_payslip', False)
name = fields.Char(required=True)
code = fields.Char(string='Reference', required=True)
company_id = fields.Many2one('res.company', string='Company', required=True,
@@ -29,6 +33,8 @@ class HrPayrollStructure(models.Model):
parent_id = fields.Many2one('hr.payroll.structure', string='Parent', default=_get_parent)
children_ids = fields.One2many('hr.payroll.structure', 'parent_id', string='Children', copy=True)
rule_ids = fields.Many2many('hr.salary.rule', 'hr_structure_salary_rule_rel', 'struct_id', 'rule_id', string='Salary Rules')
report_id = fields.Many2one('ir.actions.report',
string="Report", required=True, domain="[('model','=','hr.payslip'),('report_type','=','qweb-pdf')]", default=_get_default_report_id)
@api.constrains('parent_id')
def _check_parent_id(self):
@@ -0,0 +1,43 @@
odoo.define('hr_payroll.payslip.tree', function (require) {
"use strict";
var core = require('web.core');
var ListController = require('web.ListController');
var ListView = require('web.ListView');
var viewRegistry = require('web.view_registry');
var QWeb = core.qweb;
var PayslipListController = ListController.extend({
/**
* Extends the renderButtons function of ListView by adding a button
* on the payslip list.
*
* @override
*/
renderButtons: function () {
this._super.apply(this, arguments);
this.$buttons.append($(QWeb.render("PayslipListView.print_button", this)));
var self = this;
this.$buttons.on('click', '.o_button_print_payslip', function () {
if (self.getSelectedIds().length == 0) {
return;
}
return self._rpc({
model: 'hr.payslip',
method: 'action_print_payslip',
args: [self.getSelectedIds()],
}).then(function (results) {
self.do_action(results);
});
});
}
});
var PayslipListView = ListView.extend({
config: _.extend({}, ListView.prototype.config, {
Controller: PayslipListController,
}),
});
viewRegistry.add('hr_payroll_payslip_tree', PayslipListView);
});
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="PayslipListView.print_button">
<button type="button" class="btn btn-secondary o_button_print_payslip">
Print
</button>
</t>
</templates>
@@ -4,6 +4,7 @@
<template id="assets_backend" inherit_id="web.assets_backend">
<xpath expr="script[last()]" position="after">
<script type="text/javascript" src="/hr_payroll/static/src/js/benefit.js"></script>
<script type="text/javascript" src="/hr_payroll/static/src/js/payslip.js"></script>
</xpath>
</template>
</odoo>
+3 -2
View File
@@ -70,7 +70,7 @@
<field name="name">hr.payslip.tree</field>
<field name="model">hr.payslip</field>
<field name="arch" type="xml">
<tree decoration-info="state in ('confirm','hr_check','accont_check')" decoration-muted="state == 'cancel'" string="Payslips">
<tree decoration-info="state in ('confirm','verify')" decoration-muted="state == 'cancel'" js_class="hr_payroll_payslip_tree" string="Payslips">
<field name="number"/>
<field name="employee_id"/>
<field name="name"/>
@@ -133,7 +133,8 @@
<button string="Set to Draft" name="action_payslip_draft" type="object" states="cancel"/>
<button string="Compute Sheet" name="compute_sheet" type="object" states="draft" class="oe_highlight"/>
<button string="Cancel Payslip" name="action_payslip_cancel" type="object" states="draft,confirm,verify"/>
<field name="state" widget="statusbar" statusbar_visible="draft,verify,confirm"/>
<button string="Print" name="action_print_payslip" type="object"/>
<field name="state" widget="statusbar" statusbar_visible="draft,confirm"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
@@ -73,6 +73,7 @@
<field name="name"/>
<field name="code"/>
<field name="parent_id"/>
<field name="report_id"/>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
</group>
<notebook colspan="4">