Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
302 views
in Technique[技术] by (71.8m points)

python - How to send an email from a button located in the action dropdown of an Odoo 11 form?

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...