Creating Dynamic Reports in Odoo 17
Handling Auto-Generated Fields in Account Analytic Plans

by Sajjad Hussain

With Odoo 17, developers and businesses have access to new features that enhance functionality and streamline processes. One notable feature is the automatic creation and addition of fields when a new plan (model: account.analytic.plan) is created. While powerful, this feature presents a challenge: dynamically incorporating these new fields into reports. In this blog post, we’ll explore how to handle this issue and ensure your reports stay up-to-date with these dynamic changes.

Understanding the Challenge

When a new plan is created in Odoo 17, a corresponding field is automatically generated and added to the form view of the account.analytic.line model. This dynamic creation poses a problem for report generation because the new fields are not predefined and therefore can't be directly referenced in static report templates. This becomes particularly problematic when reports are designed and finalized, only for new plans to be added later, introducing new fields with unique technical names.

Analytic plans

In the above screenshot, we can see that three plans have been created.

So all three plan name fields are automatically added on the Analytic Items form view by odoo17, and we can see the technical name of the last created field too here.

The Solution

Numla has devised an effective solution to this problem, allowing for the dynamic retrieval of all field names from the account.analytic.line model. This ensures that reports can adapt to include any newly created fields without requiring constant manual updates. Here's a step-by-step guide on how to implement this solution.

Step 1: Retrieve the Plan Object

First, retrieve the plan object from the account.analytic.plan model. This can be done using the Odoo ORM (Object-Relational Mapping) method.

python
plan = env['account.analytic.plan'].search([('name', '=', 'Your Plan Name')], limit=1)

Step 2: Get the Technical Field Name

Once you have the plan object, you can use the _strict_column_name method to obtain the technical name of the automatically created field. This method ensures that you get the exact technical name used by Odoo 17.

python
field_name = plan._strict_column_name()

Step 3: Incorporate Dynamic Fields into Reports

With the technical field names at hand, you can now dynamically include these fields in your reports. Whether you are generating PDF or XLSX reports, you can programmatically fetch and include these fields.

Example: Generating a PDF Report

Below is an example of how you might generate a PDF report that includes the dynamically retrieved fields using the reportlab library.

python
from reportlab.lib.pagesizes import letter from reportlab.pdfgen import canvas

def generate_pdf_report(plan):
   field_name = plan._strict_column_name()
   # Fetch data from account.analytic.line including the dynamic field analytic_lines =     env['account.analytic.line'].search([])

   # Create PDF
   pdf_file = "/path/to/your/report.pdf"
   c = canvas.Canvas(pdf_file, pagesize=letter)
   width, height = letter

   # Add data to PDF
   y = height - 40
   c.drawString(30, y, "Analytic Lines Report")
   y -= 20
   for line in analytic_lines:
      # Access the dynamic field value field_value = getattr(line, field_name, 'N/A')
      c.drawString(30, y, f"{line.name}: {field_value}") y -= 20

   c.save()

# Example usage
plan = env['account.analytic.plan'].search([('name', '=', 'Your Plan Name')], limit=1) generate_pdf_report(plan)

Example: Generating an XLSX Report

Similarly, you can generate an XLSX report using the xlsxwriter library.

python
import xlsxwriter

def generate_xlsx_report(plan):
   field_name = plan._strict_column_name()
   # Fetch data from account.analytic.line including the dynamic field analytic_lines =     env['account.analytic.line'].search([])

   # Create XLSX file
   xlsx_file = "/path/to/your/report.xlsx"
   workbook = xlsxwriter.Workbook(xlsx_file)
   worksheet = workbook.add_worksheet()

   # Write headers
   worksheet.write(0, 0, 'Name')
   worksheet.write(0, 1, field_name)

    # Write data
    row = 1
    for line in analytic_lines:
       field_value = getattr(line, field_name, 'N/A')
       worksheet.write(row, 0, line.name)
       worksheet.write(row, 1, field_value)
       row += 1

       workbook.close()

# Example usage
plan = env['account.analytic.plan'].search([('name', '=', 'Your Plan Name')], limit=1) generate_xlsx_report(plan)

Conclusion

The dynamic creation of fields in Odoo 17 when new plans are added presents a unique challenge for report generation. However, by leveraging the _strict_column_name method, developers can retrieve the technical names of these fields and incorporate them into reports dynamically. This ensures that reports remain accurate and up-to-date, reflecting the most current data without requiring constant manual adjustments.

With this approach, you can confidently create robust and flexible reporting solutions in Odoo 17, accommodating the dynamic nature of your data and maintaining the integrity of your business insights.

Need more development tips?

Stay tuned to our blog.

Configure Outlook Exchange Server and Catch-All Email in Odoo