OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

problem with the cron and pdf of odoo 15 when producing the documents

  • Thread starter Thread starter SirDomini x
  • Start date Start date
S

SirDomini x

Guest
`When the invoice document is generated manually the document comes out fine, but when it is generated automatically through cron from my subscription module, it comes out with the formats out of order, and even the header or footer are not damaged automatic manual

I attach the xml code that I have to generate said document ->`

Code:
<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <data>
        <template id="report_invoice_with_payments_3_1">
            <t t-call="web.html_container">
                <t t-foreach="docs" t-as="doc">
                    <t t-call="web.basic_layout">
                        <xpath expr="." position="inside">
                            <link href="/extension_suscripcion/static/src/css/styles.css" rel="stylesheet"/>
                        </xpath>
                        <style type="text/css">
                            .page {
                                font-size: 17px;
                                font-family: Roboto;
                                position: relative;
                            }
                            .background-image {
                                height: 100%;
                                width: 100%;
                                position: absolute;
                                top: 0;
                                left: 0;
                                z-index: -1;
                                background-position: 50% 75%;
                                background-repeat: no-repeat;
                                background-image: url(/extension_suscripcion/static/src/img/image_background_radnet.jpeg);
                            }
                            .background-images {
                                <!--height: 70em;-->
                                height: 100%;
                                width: 100%;
                                position: absolute;
                                top: 0;
                                left: 0;
                                z-index: -1;
                                background-position: 90% 100%;
                                background-repeat: no-repeat;
                                background-image: url(/extension_suscripcion/static/src/img/Radnet_sello.png);
                            }
                        </style>
                        
                        <!---->
                        
                        <div class="page">
                          <div class="background-images"/>
                          <div class="background-image"/>
                            <div class="header o_company_#{company.id}_layout" style="report_header_style;">
                                <img src="/extension_suscripcion/static/src/img/radnet_logo.jpeg" alt="Radnet Logo"/>
                            </div>
                            <div style="position: relative; z-index: 100;">
                                <div id="information">
                                    <h2>Pro-forma <span t-field="doc.name"/></h2>
                                    <div t-if="doc.invoice_date" class="col-auto col-3 mw-100 mb-2" style="margin-bottom: 1px; padding-left: 75%; margin-top: -42px;">
                                        <strong>Fecha: </strong>
                                        <p class="m-0" t-esc="doc.invoice_date.strftime('%d/%m/%Y') if doc.state not in ['draft','sent'] else ''" t-field="doc.invoice_date" t-options="{'widget': 'date'}"/>
                                    </div>
                                    <div>
                                        <p>Atención: <span t-field="doc.partner_id.name"/></p>
                                        <p>Dirección: <span t-field="doc.partner_id.street"/> <span t-field="doc.partner_id.street2"/></p>
                                        <p>RIF: <span t-field="doc.partner_id.vat"/></p>
                                        <t t-foreach="doc.partner_id.child_ids" t-as="child">
                                            <p>Atención: <span t-field="child.name"/></p>
                                        </t>
                                    </div>
                                </div>
                                <br/>
                                <table name="producto" class="table table-sm">
                                    <thead>
                                        <tr style="text-align: left; background: #2A7DE1; color: white;">
                                            <th style="text-align: center;" rowspan="2"><strong>Descripción</strong></th>
                                            <th style="text-align: center;" rowspan="2">Cantidad</th>
                                            <th style="text-align: center;" rowspan="2"><strong>Precio Unitario</strong></th>
                                            <th style="text-align: center;" rowspan="2"><strong>Precio Total</strong></th>
                                        </tr>
                                    </thead>
                                    <tbody class="sale_tbody">
                                        <t t-foreach="doc.invoice_line_ids" t-as="line">
                                            <tr>
                                                <td class="text-left"><span t-field="line.name"/></td>
                                                <td class="text-center"><span t-field="line.quantity"/></td>
                                                <td class="text-center"><span t-esc="doc.currency_id.symbol"/><span t-field="line.price_unit" t-options="{'widget': 'float', 'precision': 2}"/></td>
                                                <td class="text-right"><span t-esc="doc.currency_id.symbol"/><span t-field="line.price_subtotal" t-options="{'widget': 'float', 'precision': 2}"/></td>
                                            </tr>
                                        </t>
                                    </tbody>
                                </table>
                                <div style="margin-right: 42px;" t-attf-class="#{'col-4' if report_type != 'html' else 'col-sm-7 col-md-5'} ml-auto">
                                    <table width="310px" style="page-break-inside: avoid;">
                                        <tr class="border-black o_subtotal">
                                            <td><strong>Base imponible</strong></td>
                                            <td class="text-right"><span t-esc="doc.currency_id.symbol"/><span t-field="doc.amount_untaxed" t-options="{'widget': 'float', 'precision': 2}"/></td>
                                        </tr>
                                        <tr>
                                            <td>IVA 16%</td>
                                            <td class="text-right"><span t-esc="doc.currency_id.symbol"/><span t-field="doc.amount_tax" t-options="{'widget': 'float', 'precision': 2}"/></td>
                                        </tr>
                                        <tr class="border-black o_total">
                                            <td><strong>Total</strong></td>
                                            <td class="text-right"><span t-esc="doc.currency_id.symbol"/><span t-field="doc.amount_total" t-options="{'widget': 'float', 'precision': 2}"/></td>
                                        </tr>
                                    </table>
                                </div>
                                <br/>
                            
                                <br/>
                                <div class="footer o_standard_footer o_company_#{company.id}_layout">
                                    <center>
                                        <img src="/extension_suscripcion/static/src/img/footer_radnet.jpeg" width="100%" alt="Footer Radnet"/>
                                    </center>
                                </div>
                            </div>
                        </div>
                    </t>
                </t>
            </t>
        </template>
    </data>
</odoo>

`I have restructured the code several times, I have even modified my custom subscription module where I have a code for generation with cron

and I also have the same result, attached code`

from odoo import models, fields, api, _ from odoo.exceptions import UserError from datetime import timedelta from dateutil.relativedelta import relativedelta import logging

_logger = logging.getLogger(name)

class SaleSubscription(models.Model): _inherit = 'sale.subscription'

Code:
def _should_create_invoice(self):
    """ Determine if an invoice should be created based on subscription's next invoice date """
    today = fields.Date.today()
    for subscription in self:
        if not subscription.recurring_next_date:
            return False
        return subscription.recurring_next_date <= today

def create_draft_invoice(self):
    invoices = self.env['account.move']
    for subscription in self:
        invoice_lines = []
        for line in subscription.recurring_invoice_line_ids:
            price_unit = line.product_id.currency_id._convert(
                line.price_unit, subscription.currency_id, subscription.company_id, fields.Date.today()
            )
            taxes = line.product_id.taxes_id.filtered(lambda t: t.company_id == subscription.company_id)
            tax_lines = [(6, 0, taxes.ids)]
            invoice_lines.append((0, 0, {
                'product_id': line.product_id.id,
                'quantity': line.quantity,
                'price_unit': price_unit,
                'currency_id': subscription.currency_id.id,
                'tax_ids': tax_lines,
            }))
        # Create draft invoice
        invoice = self.env['account.move'].create({
            'move_type': 'out_invoice',
            'partner_id': subscription.partner_id.id,
            'invoice_date': fields.Date.today(),
            'invoice_line_ids': invoice_lines,
            'currency_id': subscription.currency_id.id,
        })
        if subscription.analytic_account_id:
            invoice.invoice_line_ids.write({
                'analytic_account_id': subscription.analytic_account_id.id,
            })
        if subscription.tag_ids:
            invoice.invoice_line_ids.write({
                'analytic_tag_ids': [(6, 0, subscription.tag_ids.ids)],
            })
        invoices += invoice

        # Log the action on subscription thread
        subscription.message_post(
            body=f'A draft invoice has been generated: <a href="#id={invoice.id}&model=account.move">{invoice.name}</a>',
            subtype_id=self.env.ref('mail.mt_note').id
        )

        subscription.invoice_count += 1
    return invoices

@api.model
def _recurring_create_invoice(self, automatic=True):
    invoices = self.env['account.move']
    for subscription in self:
        _logger.info(f"Processing subscription: {subscription.id}")

        if subscription.template_id.payment_mode == 'draft_invoice':
            _logger.info("Creating draft invoice")
            if subscription._should_create_invoice():
                new_invoices = subscription.create_draft_invoice()
                _logger.info(f"Invoices created: {new_invoices}")
                invoices += new_invoices

                # Sending emails if draft invoice email template is configured
                if subscription.template_id.draft_invoice_email_template_id:
                    template = subscription.template_id.draft_invoice_email_template_id
                    for invoice in new_invoices:
                        _logger.info(f"Sending email for draft invoice {invoice.id}")
                        template.send_mail(invoice.id, force_send=True)

        elif subscription.template_id.payment_mode == 'validate_send':
            _logger.info("Using original method to create and validate invoices")
            new_invoices = super(SaleSubscription, subscription)._recurring_create_invoice(automatic=automatic)
            invoices += new_invoices

            # Sending emails if draft invoice email template is configured
            if subscription.template_id.draft_invoice_email_template_id:
                template = subscription.template_id.draft_invoice_email_template_id
                for invoice in new_invoices:
                    _logger.info(f"Sending email for validated invoice {invoice.id}")
                    template.send_mail(invoice.id, force_send=True)

        # Update next invoice date based on subscription setting
        if invoices:
            next_date = subscription.recurring_next_date or fields.Date.today()
            next_date = subscription._get_next_invoice_date(next_date)
            subscription.recurring_next_date = next_date
            _logger.info(f"Next invoice date for subscription {subscription.id}: {subscription.recurring_next_date}")

    return invoices

def _get_next_invoice_date(self, current_date):
    """ Calculate the next invoice date based on the current date and the subscription period """
    interval = self.template_id.recurring_interval
    period = self.template_id.recurring_rule_type
    if period == 'daily':
        return current_date + timedelta(days=interval)
    elif period == 'weekly':
        return current_date + timedelta(weeks=interval)
    elif period == 'monthly':
        return current_date + relativedelta(months=interval)
    elif period == 'yearly':
        return current_date + relativedelta(years=interval)
    return current_date

def validate_and_send_invoice(self, invoice):
    self.ensure_one()
    if invoice.state != 'posted':
        invoice._post(False)
    email_context = self.env.context.copy()
    email_context.update({
        'total_amount': invoice.amount_total,
        'email_to': self.partner_id.email,
        'code': self.code,
        'currency': self.pricelist_id.currency_id.name,
        'date_end': self.date,
        'mail_notify_force_send': False,
        'no_new_invoice': True,
    })
    _logger.debug("Sending Invoice Mail to %s for subscription %s", self.partner_id.email, self.id)
    invoice.with_context(email_context, print_mode=True).message_post_with_template(self.template_id.invoice_mail_template_id.id)
    invoice.is_move_sent = True
    if hasattr(invoice, "attachment_ids") and invoice.attachment_ids:
        invoice._message_set_main_attachment_id([(4, id) for id in invoice.attachment_ids.ids])
        
@api.model
def _cron_recurring_create_invoice(self):
    subscriptions = self.search([('stage_category', '=', 'progress')])
    invoices = subscriptions._recurring_create_invoice(automatic=True)
    return len(invoices)

@api.model
def _cron_update_kpi(self):
    subscriptions = self.search([('stage_category', '=', 'progress')])
    subscriptions._compute_kpi()
    return len(subscriptions)

class SaleSubscriptionTemplate(models.Model): _inherit = 'sale.subscription.template'

Code:
payment_mode = fields.Selection([
    ('manual', 'Manualmente'),
    ('draft_invoice', 'Borrador'),
    ('validate_send', 'Publicar'),
    ('success_payment', 'Enviar después de que el pago sea exitoso'),
], string='Modo de pago', default='manual')

draft_invoice_email_template_id = fields.Many2one(
    'mail.template', 
    string='Draft Invoice Email Template',
    help='Email template to use when creating draft invoices.'
)
<p>`When the invoice document is generated manually the document comes out fine, but when it is generated automatically through cron from my subscription module, it comes out with the formats out of order, and even the header or footer are not damaged <a href="https://i.sstatic.net/KKIhaxGy.jpg" rel="nofollow noreferrer">automatic</a> <a href="https://i.sstatic.net/z1tyYPr5.jpg" rel="nofollow noreferrer">manual</a></p>
<p>I attach the xml code that I have to generate said document ->`</p>
<pre><code><?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="report_invoice_with_payments_3_1">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="doc">
<t t-call="web.basic_layout">
<xpath expr="." position="inside">
<link href="/extension_suscripcion/static/src/css/styles.css" rel="stylesheet"/>
</xpath>
<style type="text/css">
.page {
font-size: 17px;
font-family: Roboto;
position: relative;
}
.background-image {
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: -1;
background-position: 50% 75%;
background-repeat: no-repeat;
background-image: url(/extension_suscripcion/static/src/img/image_background_radnet.jpeg);
}
.background-images {
<!--height: 70em;-->
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: -1;
background-position: 90% 100%;
background-repeat: no-repeat;
background-image: url(/extension_suscripcion/static/src/img/Radnet_sello.png);
}
</style>

<!---->

<div class="page">
<div class="background-images"/>
<div class="background-image"/>
<div class="header o_company_#{company.id}_layout" style="report_header_style;">
<img src="/extension_suscripcion/static/src/img/radnet_logo.jpeg" alt="Radnet Logo"/>
</div>
<div style="position: relative; z-index: 100;">
<div id="information">
<h2>Pro-forma <span t-field="doc.name"/></h2>
<div t-if="doc.invoice_date" class="col-auto col-3 mw-100 mb-2" style="margin-bottom: 1px; padding-left: 75%; margin-top: -42px;">
<strong>Fecha: </strong>
<p class="m-0" t-esc="doc.invoice_date.strftime('%d/%m/%Y') if doc.state not in ['draft','sent'] else ''" t-field="doc.invoice_date" t-options="{'widget': 'date'}"/>
</div>
<div>
<p>Atención: <span t-field="doc.partner_id.name"/></p>
<p>Dirección: <span t-field="doc.partner_id.street"/> <span t-field="doc.partner_id.street2"/></p>
<p>RIF: <span t-field="doc.partner_id.vat"/></p>
<t t-foreach="doc.partner_id.child_ids" t-as="child">
<p>Atención: <span t-field="child.name"/></p>
</t>
</div>
</div>
<br/>
<table name="producto" class="table table-sm">
<thead>
<tr style="text-align: left; background: #2A7DE1; color: white;">
<th style="text-align: center;" rowspan="2"><strong>Descripción</strong></th>
<th style="text-align: center;" rowspan="2">Cantidad</th>
<th style="text-align: center;" rowspan="2"><strong>Precio Unitario</strong></th>
<th style="text-align: center;" rowspan="2"><strong>Precio Total</strong></th>
</tr>
</thead>
<tbody class="sale_tbody">
<t t-foreach="doc.invoice_line_ids" t-as="line">
<tr>
<td class="text-left"><span t-field="line.name"/></td>
<td class="text-center"><span t-field="line.quantity"/></td>
<td class="text-center"><span t-esc="doc.currency_id.symbol"/><span t-field="line.price_unit" t-options="{'widget': 'float', 'precision': 2}"/></td>
<td class="text-right"><span t-esc="doc.currency_id.symbol"/><span t-field="line.price_subtotal" t-options="{'widget': 'float', 'precision': 2}"/></td>
</tr>
</t>
</tbody>
</table>
<div style="margin-right: 42px;" t-attf-class="#{'col-4' if report_type != 'html' else 'col-sm-7 col-md-5'} ml-auto">
<table width="310px" style="page-break-inside: avoid;">
<tr class="border-black o_subtotal">
<td><strong>Base imponible</strong></td>
<td class="text-right"><span t-esc="doc.currency_id.symbol"/><span t-field="doc.amount_untaxed" t-options="{'widget': 'float', 'precision': 2}"/></td>
</tr>
<tr>
<td>IVA 16%</td>
<td class="text-right"><span t-esc="doc.currency_id.symbol"/><span t-field="doc.amount_tax" t-options="{'widget': 'float', 'precision': 2}"/></td>
</tr>
<tr class="border-black o_total">
<td><strong>Total</strong></td>
<td class="text-right"><span t-esc="doc.currency_id.symbol"/><span t-field="doc.amount_total" t-options="{'widget': 'float', 'precision': 2}"/></td>
</tr>
</table>
</div>
<br/>

<br/>
<div class="footer o_standard_footer o_company_#{company.id}_layout">
<center>
<img src="/extension_suscripcion/static/src/img/footer_radnet.jpeg" width="100%" alt="Footer Radnet"/>
</center>
</div>
</div>
</div>
</t>
</t>
</t>
</template>
</data>
</odoo>
</code></pre>
<p>`I have restructured the code several times, I have even modified my custom subscription module where I have a code for generation with cron</p>
<p>and I also have the same result, attached code`</p>
<p>from odoo import models, fields, api, _
from odoo.exceptions import UserError
from datetime import timedelta
from dateutil.relativedelta import relativedelta
import logging</p>
<p>_logger = logging.getLogger(<strong>name</strong>)</p>
<p>class SaleSubscription(models.Model):
_inherit = 'sale.subscription'</p>
<pre><code>def _should_create_invoice(self):
""" Determine if an invoice should be created based on subscription's next invoice date """
today = fields.Date.today()
for subscription in self:
if not subscription.recurring_next_date:
return False
return subscription.recurring_next_date <= today

def create_draft_invoice(self):
invoices = self.env['account.move']
for subscription in self:
invoice_lines = []
for line in subscription.recurring_invoice_line_ids:
price_unit = line.product_id.currency_id._convert(
line.price_unit, subscription.currency_id, subscription.company_id, fields.Date.today()
)
taxes = line.product_id.taxes_id.filtered(lambda t: t.company_id == subscription.company_id)
tax_lines = [(6, 0, taxes.ids)]
invoice_lines.append((0, 0, {
'product_id': line.product_id.id,
'quantity': line.quantity,
'price_unit': price_unit,
'currency_id': subscription.currency_id.id,
'tax_ids': tax_lines,
}))
# Create draft invoice
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': subscription.partner_id.id,
'invoice_date': fields.Date.today(),
'invoice_line_ids': invoice_lines,
'currency_id': subscription.currency_id.id,
})
if subscription.analytic_account_id:
invoice.invoice_line_ids.write({
'analytic_account_id': subscription.analytic_account_id.id,
})
if subscription.tag_ids:
invoice.invoice_line_ids.write({
'analytic_tag_ids': [(6, 0, subscription.tag_ids.ids)],
})
invoices += invoice

# Log the action on subscription thread
subscription.message_post(
body=f'A draft invoice has been generated: <a href="#id={invoice.id}&model=account.move">{invoice.name}</a>',
subtype_id=self.env.ref('mail.mt_note').id
)

subscription.invoice_count += 1
return invoices

@api.model
def _recurring_create_invoice(self, automatic=True):
invoices = self.env['account.move']
for subscription in self:
_logger.info(f"Processing subscription: {subscription.id}")

if subscription.template_id.payment_mode == 'draft_invoice':
_logger.info("Creating draft invoice")
if subscription._should_create_invoice():
new_invoices = subscription.create_draft_invoice()
_logger.info(f"Invoices created: {new_invoices}")
invoices += new_invoices

# Sending emails if draft invoice email template is configured
if subscription.template_id.draft_invoice_email_template_id:
template = subscription.template_id.draft_invoice_email_template_id
for invoice in new_invoices:
_logger.info(f"Sending email for draft invoice {invoice.id}")
template.send_mail(invoice.id, force_send=True)

elif subscription.template_id.payment_mode == 'validate_send':
_logger.info("Using original method to create and validate invoices")
new_invoices = super(SaleSubscription, subscription)._recurring_create_invoice(automatic=automatic)
invoices += new_invoices

# Sending emails if draft invoice email template is configured
if subscription.template_id.draft_invoice_email_template_id:
template = subscription.template_id.draft_invoice_email_template_id
for invoice in new_invoices:
_logger.info(f"Sending email for validated invoice {invoice.id}")
template.send_mail(invoice.id, force_send=True)

# Update next invoice date based on subscription setting
if invoices:
next_date = subscription.recurring_next_date or fields.Date.today()
next_date = subscription._get_next_invoice_date(next_date)
subscription.recurring_next_date = next_date
_logger.info(f"Next invoice date for subscription {subscription.id}: {subscription.recurring_next_date}")

return invoices

def _get_next_invoice_date(self, current_date):
""" Calculate the next invoice date based on the current date and the subscription period """
interval = self.template_id.recurring_interval
period = self.template_id.recurring_rule_type
if period == 'daily':
return current_date + timedelta(days=interval)
elif period == 'weekly':
return current_date + timedelta(weeks=interval)
elif period == 'monthly':
return current_date + relativedelta(months=interval)
elif period == 'yearly':
return current_date + relativedelta(years=interval)
return current_date

def validate_and_send_invoice(self, invoice):
self.ensure_one()
if invoice.state != 'posted':
invoice._post(False)
email_context = self.env.context.copy()
email_context.update({
'total_amount': invoice.amount_total,
'email_to': self.partner_id.email,
'code': self.code,
'currency': self.pricelist_id.currency_id.name,
'date_end': self.date,
'mail_notify_force_send': False,
'no_new_invoice': True,
})
_logger.debug("Sending Invoice Mail to %s for subscription %s", self.partner_id.email, self.id)
invoice.with_context(email_context, print_mode=True).message_post_with_template(self.template_id.invoice_mail_template_id.id)
invoice.is_move_sent = True
if hasattr(invoice, "attachment_ids") and invoice.attachment_ids:
invoice._message_set_main_attachment_id([(4, id) for id in invoice.attachment_ids.ids])

@api.model
def _cron_recurring_create_invoice(self):
subscriptions = self.search([('stage_category', '=', 'progress')])
invoices = subscriptions._recurring_create_invoice(automatic=True)
return len(invoices)

@api.model
def _cron_update_kpi(self):
subscriptions = self.search([('stage_category', '=', 'progress')])
subscriptions._compute_kpi()
return len(subscriptions)
</code></pre>
<p>class SaleSubscriptionTemplate(models.Model):
_inherit = 'sale.subscription.template'</p>
<pre><code>payment_mode = fields.Selection([
('manual', 'Manualmente'),
('draft_invoice', 'Borrador'),
('validate_send', 'Publicar'),
('success_payment', 'Enviar después de que el pago sea exitoso'),
], string='Modo de pago', default='manual')

draft_invoice_email_template_id = fields.Many2one(
'mail.template',
string='Draft Invoice Email Template',
help='Email template to use when creating draft invoices.'
)
</code></pre>
 

Latest posts

Top