# Part of the odoo-at-payroll project. License: LGPL-3. """Wizard: Dokument aus Vorlage generieren. Befüllt die Platzhalter der Vorlage aus hr-Stammdaten (automatische Felder) und Wizard-Eingaben (manuelle Felder), rendert eine Vorschau und erzeugt PDF (ir.actions.report, wkhtmltopdf) bzw. — ohne PDF-Engine — das gerenderte HTML als Anhang. """ import base64 from markupsafe import Markup from odoo import api, fields, models, _ from odoo.exceptions import UserError from odoo.tools.misc import format_date class L10nAtPayrollDokumentWizard(models.TransientModel): _name = 'l10n.at.payroll.dokument.wizard' _description = 'Dokument aus Vorlage generieren' vorlage_id = fields.Many2one( 'l10n.at.payroll.dokument.vorlage', required=True, domain=[('active', '=', True)]) employee_id = fields.Many2one('hr.employee', required=True) datum = fields.Date( string='Stichtag', default=fields.Date.context_today, help="Stichtag für den hr.version-Stand (Vertragsdaten).") version_id = fields.Many2one( 'hr.version', compute='_compute_version_id', string='Vertragsstand (hr.version)') feld_wert_ids = fields.One2many( 'l10n.at.payroll.dokument.wizard.feld', 'wizard_id', string='Befüllung') vorschau_html = fields.Html( string='Vorschau', readonly=True, sanitize=False) @api.depends('employee_id', 'datum') def _compute_version_id(self): for wizard in self: wizard.version_id = wizard._at_version_am() def _at_version_am(self): """hr.version gültig am Stichtag (date_version <= Stichtag).""" self.ensure_one() if not self.datum or not self.employee_id: return self.env['hr.version'] return self.env['hr.version'].search( [('employee_id', '=', self.employee_id.id), ('date_version', '<=', self.datum)], order='date_version desc, id desc', limit=1) @api.onchange('vorlage_id') def _onchange_vorlage_id(self): self.vorschau_html = False self.feld_wert_ids = self._at_linien() def action_befuellen(self): """Linien aus der Vorlage neu aufbauen (auch bei Wechsel).""" self.ensure_one() self.vorschau_html = False self.feld_wert_ids = self._at_linien() def _at_linien(self): self.ensure_one() if not self.vorlage_id: return [(5, 0, 0)] return [(5, 0, 0)] + [ (0, 0, { 'key': feld.key, 'bezeichnung': feld.bezeichnung, 'quelle': feld.quelle, 'pflicht': feld.pflicht, 'hinweis': feld.hinweis, }) for feld in self.vorlage_id.feld_ids.sorted('sequence') ] def _at_werte(self): """Befüllwerte: automatisch aufgelöst + manuelle Eingaben.""" self.ensure_one() werte = {} fehlen = [] for feld in self.vorlage_id.feld_ids: line = self.feld_wert_ids.filtered( lambda l, k=feld.key: l.key == k)[:1] if feld.quelle == 'auto': werte[feld.key] = self._at_auto_wert(feld.key) else: wert = (line.wert or '').strip() if not wert and feld.pflicht: fehlen.append(feld.bezeichnung or feld.key) werte[feld.key] = wert if fehlen: raise UserError(_( "Pflichtfelder nicht befüllt: %s", ', '.join(fehlen))) return werte def _at_auto_wert(self, key): self.ensure_one() employee = self.employee_id version = self.version_id company = employee.company_id if key == 'firma': return company.name or '' if key == 'firma_strasse': return company.partner_id.street or '' if key == 'firma_plz': return company.partner_id.zip or '' if key == 'firma_ort': return company.partner_id.city or '' if key == 'mitarbeiter': return employee.name or '' if key == 'mitarbeiter_strasse': return version.private_street or '' if key == 'mitarbeiter_plz': return version.private_zip or '' if key == 'mitarbeiter_ort': return version.private_city or '' if key == 'ead': datum = version.date_version or version.contract_date_start return format_date(self.env, datum) if datum else '' if key == 'funktion': return version.job_title or version.job_id.name or '' if key == 'geboren': return format_date(self.env, employee.birthday) if employee.birthday else '' raise UserError(_( "Kein automatischer Wert für Platzhalter '%s' definiert.", key)) def action_vorschau(self): self.ensure_one() werte = self._at_werte() self.vorschau_html = Markup(self.vorlage_id._at_renderen( self.employee_id, self.version_id, werte, self.datum)) return { 'type': 'ir.actions.act_window', 'res_model': self._name, 'res_id': self.id, 'view_mode': 'form', 'target': 'new', } def action_pdf(self): self.ensure_one() werte = self._at_werte() body = Markup(self.vorlage_id._at_renderen( self.employee_id, self.version_id, werte, self.datum)) name = '%s — %s (%s)' % ( self.vorlage_id.name, self.employee_id.name, self.datum) if self.env['ir.actions.report'].get_wkhtmltopdf_state() == 'ok': pdf_content, _typ = self.env['ir.actions.report']._render_qweb_pdf( 'l10n_at_payroll_dokumente.action_report_dokument_generisch', self.ids, data={'titel': name, 'body': body}) datas = base64.b64encode(pdf_content) mimetype = 'application/pdf' suffix = '.pdf' else: datas = base64.b64encode(str(body).encode('utf-8')) mimetype = 'text/html' suffix = '.html' self.env['ir.attachment'].create({ 'name': name + suffix, 'datas': datas, 'mimetype': mimetype, 'res_model': 'hr.employee', 'res_id': self.employee_id.id, 'description': 'Dokument aus Vorlage %s' % self.vorlage_id.name, }) return { 'type': 'ir.actions.act_window_close', } class L10nAtPayrollDokumentWizardFeld(models.TransientModel): _name = 'l10n.at.payroll.dokument.wizard.feld' _description = 'Dokument-Wizard Befüllzeile' wizard_id = fields.Many2one( 'l10n.at.payroll.dokument.wizard', required=True, ondelete='cascade') key = fields.Char(readonly=True, required=True) bezeichnung = fields.Char(readonly=True) quelle = fields.Selection( [('auto', 'Automatisch (hr-Stammdaten)'), ('manuell', 'Manuelle Eingabe im Wizard')], readonly=True) pflicht = fields.Boolean(readonly=True) hinweis = fields.Char(readonly=True) wert = fields.Char()