1

I am just a newbie in Odoo. I am creating a custom module for Odoo 11. I want to add a new link in hr.payslip in hr_payroll module . So when admin will navigate to an individual Payslip, in the action I want to add a new option called Email Payslip. When this is clicked, it will send an email to the employee.

So to achieve this I have made my custom module named as email payslip.

The code is like this:

init.py

from . import models

manifest.py

{
    'name': 'Email Payslip',
    'summary': """This module will send email with payslip""",
    'version': '10.0.1.0.0',
    'description': """This module will send email with payslip""",
    'author': 'Test',
    'company': 'test',
    'website': 'https://test.com',
    'category': 'Tools',
    'depends': ['base'],
    'license': 'AGPL-3',
    'data': [
        'views/email_payslip.xml',
    ],
    'demo': [],
    'installable': True,
    'auto_install': False,
}

Models init.py

from . import email_payslip

Models email_payslip.py

import babel
from datetime import date, datetime, time
from dateutil.relativedelta import relativedelta
from pytz import timezone

from odoo import api, fields, models, tools, _
from odoo.addons import decimal_precision as dp
from odoo.exceptions import UserError, ValidationError

class EmailPayslip(models.Model):
    #print 'sdabhd'
    _name = 'email.payslip'
    name = fields.Char(string="Title", required=True)
    description = 'Email Payslip'

EmailPayslip()

Views email_payslip.xml

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<act_window id="email_payslip" src_model="hr.payslip" res_model="hr.payslip.line"  name="Email Payslip"/>
</odoo>

The above code shows the email payslip menu in the action but when I am clicking on the link it is showing the employee payslip record.

So can someone help me here? What would be the right approach to achieve this? Any help and suggestions will be really appreciated.

This is what I have got so far:

Preview

forvas
  • 9,801
  • 7
  • 62
  • 158
NewUser
  • 12,713
  • 39
  • 142
  • 236

1 Answers1

3

I have understood that you want to add a button in the actions section of the form of the model hr.payslip, created by the module hr_payroll.

I see that you are creating a new model named email.payslip. That is not necessary to achieve your purpose, check the following steps:

Modify the __manifest__.py of your module to make it depend on hr_payroll and mail:

'depends': [
    'hr_payroll',
    'mail',
],

Modify your XML action this way:

<record id="action_email_payslip" model="ir.actions.server">
    <field name="name">Email Payslip</field>
    <field name="model_id" ref="hr_payroll.model_hr_payslip"/>
    <field name="binding_model_id" ref="hr_payroll.model_hr_payslip"/>
    <field name="state">code</field>
    <field name="code">
if records:
    action = records.action_email_payslip_send()
    </field>
</record>

This is to create a button in the actions section of the views of the model hr.payslip. The button will call a Python method of this model, which will be in charge of calling the pop-up to send an email.

Now let's define that method in Python:

class HrPayslip(models.Model):
    _inherit = 'hr.payslip'

    @api.multi
    def action_email_payslip_send(self):
        self.ensure_one()
        template = self.env.ref(
            'your_module.email_template_payslip',
            False,
        )
        compose_form = self.env.ref(
            'mail.email_compose_message_wizard_form',
            False,
        )
        ctx = dict(
            default_model='hr.payslip',
            default_res_id=self.id,
            default_use_template=bool(template),
            default_template_id=template and template.id or False,
            default_composition_mode='comment',
        )
        return {
            'name': _('Compose Email'),
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'mail.compose.message',
            'views': [(compose_form.id, 'form')],
            'view_id': compose_form.id,
            'target': 'new',
            'context': ctx,
        }

Just replace your_module by the technical name of your module. This method will open the form to send an email, and we are telling it to load by default our custom email template, whose XML ID is email_template_payslip.

Now, we have to define that email template in XML. Create a new folder named data in the root path of your module, put inside the XML file, for example, named email_template_data.xml. Do not forget to add in the data key of your __manifest__.py the line 'data/email_template_data.xml', to tell your module that it must load that XML file content:

<?xml version="1.0" encoding="UTF-8"?>
<odoo noupdate="0">

        <record id="email_template_payslip" model="mail.template">
            <field name="name">Payslip - Send by Email</field>
            <field name="email_from">${(user.email or '')|safe}</field>                
            <field name="subject">${object.company_id.name|safe} Payslip (Ref ${object.name or 'n/a' })</field>
            <field name="email_to">${(object.employee_id.work_email or '')|safe}</field>
            <field name="model_id" ref="hr_payroll.model_hr_payslip"/>
            <field name="auto_delete" eval="True"/>
            <field name="lang">${(object.employee_id.user_id.lang or user.lang)}</field>
            <field name="body_html"><![CDATA[
<div style="font-family: 'Lucida Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; ">

    <p>Hello ${object.employee_id.name},</p>

    <p>Here is your payslip from ${object.company_id.name}: </p>

    <p style="border-left: 1px solid #8e0000; margin-left: 30px;">
       &nbsp;&nbsp;Name: <strong>${object.name}</strong><br />
    </p>
    <p>If you have any question, do not hesitate to contact us.</p>
    <p>Thank you for choosing ${object.company_id.name or 'us'}!</p>
    <br/>
    <br/>
</div>
            ]]></field>
        </record>

</odoo>

In the ctx variable you have every data you added in the Python method. In the object variable, every field of the current hr.payslip record. You can use dot notation to reach any relational field. Check out other email templates to learn more about Mako language.

If you definitely want to use your model email.payslip, you should do almost the same process (depending on what you want exactly) and replace the hr.payslip references by email.payslip ones.

Once you are pretty sure that you are making any modification no more on your email template, you can turn the noupdate attribute to 1, to let Odoo users to customise the email template from the interface without losing their changes in case your module is updated:

<odoo noupdate="1">
    ...
</odoo>

Once you see the email pop-up and the template loaded OK by default, remember to check these three steps:

  1. The work email of the employee of the current payslip record must be filled in (since it is the destination of the email).
  2. You must have configured your outgoing mail server.
  3. Check the cron task Mail: Email Queue Manager. It must be active and running each minute (if you want to send the email in one minute at the most), or just click on Run Manually. Also the parameter force_send could be set to True in the email, in order to not depend on cron jobs.
forvas
  • 9,801
  • 7
  • 62
  • 158
  • can you share some git repo for this? – NewUser May 07 '19 at 10:05
  • This also showed me an error like Traceback (most recent call last): File "/usr/lib/python3/dist-packages/odoo/tools/safe_eval.py", line 350, in safe_eval return unsafe_eval(c, globals_dict, locals_dict) File "", line 1, in AttributeError: 'hr.payslip' object has no attribute 'action_email_payslip_send' – NewUser May 07 '19 at 10:13
  • Here you have a standard example of how to send a mail: https://github.com/OCA/stock-logistics-workflow/tree/11.0/stock_picking_send_by_mail. And here you have several examples of server actions: https://github.com/OCA/OCB/blob/11.0/addons/crm/views/crm_lead_views.xml. Combine both to send an email from a top action button. – forvas May 07 '19 at 10:15
  • What about this? Traceback (most recent call last): File "/usr/lib/python3/dist-packages/odoo/tools/safe_eval.py", line 350, in safe_eval return unsafe_eval(c, globals_dict, locals_dict) File "", line 1, in AttributeError: 'hr.payslip' object has no attribute 'action_email_payslip_send' – NewUser May 07 '19 at 10:17
  • That error is because Odoo does not know that you have added that method in Python... could be because you have to include the *.py file where you pasted the Python code I write you in the `__init__.py`, and restart Odoo. – forvas May 07 '19 at 10:19
  • Still I am getting the same error on restart. Here is the github repo https://github.com/kshirodpatel/email-payslip . Let me know what I am missing. – NewUser May 07 '19 at 10:28
  • In `model.py`, replace `from odoo import models, fields` by `from odoo import models, fields, api, _`. We are using libraries that you are not importing. – forvas May 07 '19 at 10:36
  • Do you mean how to add a PDF to the salary slip email template? – forvas May 10 '19 at 11:53
  • Yes. I want to attache the PDF automatically to the template. – NewUser May 10 '19 at 11:55
  • Add this to your email template: `` and `A custom name for the downloaded file`. – forvas May 10 '19 at 11:59
  • The external xml id would be hr_payroll.model_hr_payslip ? – NewUser May 10 '19 at 12:03
  • I want the payslilip details in the pdf attachment in my case. – NewUser May 10 '19 at 12:05
  • No, that is not the external XML ID. You want to attach a report to the email template. That report must already exist, if not, you have to do the whole report in Qweb language. Once it exists, you have to put its external XML ID in the line I wrote you above. Explaining how to do that is too long. I recommend you to simplify your questions and ask those details in different posts. If not, none is going to answer all of them in a single answer. Please, I think the main question of this one is solved. – forvas May 10 '19 at 12:10
  • can you help me here in another question https://stackoverflow.com/questions/56108578/odoo-11-add-different-action-menu-in-two-different-area-for-the-same-model – NewUser May 13 '19 at 08:40
  • Check out the `email_from` in the XML of the email template, because I had a syntax error, a missing parenthesis. I have edited this answer to correct it. – forvas May 15 '19 at 13:33