Skip to content

Instantly share code, notes, and snippets.

@rockavoldy
Last active April 29, 2024 10:04
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save rockavoldy/46350ed3d37662ae9e2cc47ea7fb916a to your computer and use it in GitHub Desktop.
Save rockavoldy/46350ed3d37662ae9e2cc47ea7fb916a to your computer and use it in GitHub Desktop.
Odoo Cheatsheet

Odoo Cheatsheet

This gist are moved to the repository here. I will leave this gist and will update new notes directly to the repository. You can easily contribute if you want!

Welcome to OCA (Odoo Cheatsheet Akhmad 😛). Here are my notes and some useful links that i usually face them on my day-to-day working with Odoo.

Table of Contents

  1. Some useful links
  2. PDF Reporting thingies
    1. Create custom button to download pdf report
    2. View report directly via URL
    3. Internationalization odoo pdf reporting
    4. Report not consistently showing header and footer
  3. Backup and Restore DB
    1. Restore DB
    2. Backup DB
  4. Odoo unit test
    1. Odoo 11
    2. Odoo 12 and 13
    3. odoo 14 and 15
  5. Many2many field, and how to use them
  6. Run odoo with vscode debugger with debugpy

Extend expiration date db (for development)

UPDATE ir_config_parameter SET value = value::DATE + INTERVAL '1 month' WHERE key = 'database.expiration_date';

Fields level access for specific group only

If you want to give access like edit a specific field for only specific group, and you can't use attribute groups for that field since you want it shown to another group too. Then for this case, you need to make that field readonly first with readonly="1", then create a new inherited view from that view, and add attribute groups to that inherited view so that this view can only be rendered if user have that group, and just change attribute readonly on field before with False. Now you get what you wanted. Source

Some noteable things

  • Qweb t-esc and t-field; t-esc will print the key of Selection, while t-field will print the label of the selection.
  • Restrict kanban from moving records; while Odoo 13 and up have new attribute records_draggable="1", odoo 12 and below don't have that attribute. So, you need this custom module or create your field widget by yourself.
  • It seems widget="selection" have some limitation on how many data can be shown. So if the data is too much, consider refactor that one with many2one field (and it's an improvement since you now have that search functionality).
  • When you use sql_constraints, keep in mind that you can't easily remove the constraints by removing the line of code, because it's already applied to db. If you don't have access to the database directly, this is the workaround to "remove" that SQL constraints.

Some PDF reporting thingies

Create custom button to download report

  • if the button is inside that model you want to download, you can easily use type="action", so it would be
    <button name="%(studypermit_form)d" string="Download PDF" type="action" />
    that studypermit_form is id of the model ir.actions.report that already created on that module
  • if the button is inside wizard, which is not the same model, you can create action method, and just call that action method from button with type="object" and name pointed to that method
    <button name="action_download" type="object" string="Download PDF" />
    and inside that action_download is
    def action_download(self):
        template = self.env.ref('project_task_form.studypermit_form')
        
        return template.report_action(self.res_id)
    point template to the model ir.actions.report, and pass id of the resources to parameter

View report directly via URL

Internationalization report odoo 11

Report not consistent showing header and footer

Backup and restore db (not specifically odoo things, but useful)

Restore DB

  1. When it's dumped as gz, use gunzip to extract and pipe directly to psql
    gunzip -c <filename.gz> | psql <dbname>
  2. When it's dumped with pg_dump, use pg_restore and restore with no-owner, so new db will reset the owner, and fix the error
    pg_restore -d <dbname> --role=<role> -O <filename.dump>
  3. When it's dumped as zip through DB Manager Odoo, restore them from http://<server-address:port>/web/database/manager

Backup DB

  1. When you want to dump it as gunzip, so you can extract and pipe directly to psql
    pg_dump <dbname> | gzip > <filename.gz>
  2. When you want to create backup with pg_restore custom (space friendly like gunzipped)
    pg_dump -Fc <dbname> > <filename.dump>
    OR
    pg_dump -Fc -f <filename.dump> <dbname>
  3. When you want to backup as plain text postgresql query (not space friendly since it's not compressed, but you can directly edit to that query)
    pg_dump -Fp -f <filename.sql> <dbname>
  4. When you want to keep filestore of your db, backup through DB Manager Odoo on http://<server-address:port>/web/database/manager

Odoo unit test

Odoo 11

Odoo 11 don't have test-tags, so if you don't use --stop-after-init flag, it will run all the test from all modules. So then you need to run it like below. (you can change -u flag to -i flag if the module is not installed on that database)

python3 odoo-bin -c <conf_file.conf> -d <db_name> --test-enable --stop-after-init -u <module to test>

command above will update (or install) the module, run the test for that module, and will stop the process after the test on that module is done.

Odoo 12 and Odoo 13

on Odoo 12 and 13, There is --test-tags flag that you can use when you want to only run specific test that have tags. To implement it on your module, you can find the documentation here

python3 odoo-bin -c <conf_file.conf> -d <db_name> --test-enable --test-tags "tag_1,tag_2,tag_3" --stop-after-init -u <module to test>

Odoo 14 and Odoo 15

There is an improvement to how flag --test-tags works, you can point it directly to the test method or class, so you don't need to always set the tags when you want to run another unit test on others module (like base). And your CLI command will be like this

python3 odoo-bin -c <conf_file.conf> -d <db_name> --test-enable --test-tags "/<module>:<class>.<method>" --stop-after-init -u <module to test>

you can find the documentation here to add tag to your class, and for the improvement on --test-tags flag, can check them here

Many2many field, and how to use them

  • (0, 0, { values }) link to a new record that needs to be created with the given values dictionary
  • (1, ID, { values }) update the linked record with id = ID (write values on it)
  • (2, ID) remove and delete the linked record with id = ID (calls unlink on ID, that will delete the object completely, and the link to it as well)
  • (3, ID) cut the link to the linked record with id = ID (delete the relationship between the two objects but does not delete the target object itself)
  • (4, ID) link to existing record with id = ID (adds a relationship)
  • (5) unlink all (like using (3,ID) for all linked records)
  • (6, 0, [IDs]) replace the list of linked IDs (like using (5) then (4,ID) for each ID in the list of IDs)

Source

  1. Say, you want to add new group maintenance.group_user_manager to your view groups_id. it can be done with id 4 or 6, but if you want to append to existing group that already set somewhere, it must convenient to use id 4. the usage will be
<field name="groups_id" eval="(4, ref('maintenance.group_user_manager')" />

want to use them on python? can do it easily with ORM write (or update, or assignment directly as you would to change the field value)

asset = self.env['account.assets.assets'].browse(50)
asset.write({
    'depreciation_line_ids': (0, 0, {
            'name': '....',
            .....
        })
})
  1. And say, you are in app Sale, and you have some product_line, you want to remove some line but don't want to remove the product completely, can use (3, id_of_the_line_you_want_to_remove)

Run odoo with vscode debugger using debugpy

Current version of VSCode (1.64.0) has plenty of features that can be used to improve developer experience, one of this feature is Debugger. With this debugger, you can create a breakpoint and odoo will pause it on that breakpoint, then you can see the call stack that will reach to that breakpoint. So for odoo, we will use debugpy. This debugpy can run as a standalone app and something can attach to the listen host and port you already defined with flag --listen, but vscode can make it listen directly so it will more simple to use. Run debugpy from terminal, and wait for anything attached to debugpy

python3 -m debugpy --wait-for-client --listen 0.0.0.0:5678 odoo-bin <your-usual-odoo-command>

Example:

python3 -m debugpy --wait-for-client --listen 0.0.0.0:5678 odoo-bin -c odoo.conf -d odoo13

For this tutorial, i have an assumption that you already have your configuration to run and develop your odoo locally, so we just need to migrate that command or configuration to vscode launch.json

  1. Install debugpy first with pip

    pip3 install debugpy
  2. Then create directory .vscode inside your workspace and a new file called launch.json inside that .vscode directory.

  3. See below json script, this is the example to run odoo with debugpy on the launch.json file. Personalize it with your configuration to the args section. Usually, i will run odoo with command

    <cd to the workspace directory>
    python3 odoo-bin -c odoo.conf -d odoo13

    So, the launch.json can be

      {
        "version": "0.2.0",
        "configurations": [
          {
            "name": "Odoo - Start With Debugger",
            "type": "python",
            "python": "<absolute-path-to-your-python-bin>",
            "request": "launch",
            "module": "debugpy",
            "stopOnEntry": false,
            "args": [
              "--wait-for-client",
              "${workspaceRoot}/odoo-bin",
              "-c",
              "${workspaceRoot}/odoo.conf",
              "-d",
              "odoo13"
            ],
            "cwd": "${workspaceRoot}"
          },
          {
            "name": "Python - Attach debugger",
            "type": "python",
            "request": "attach",
            "port": 5678,
            "host": "localhost"
          }
        ]
      }

    change args section with your way to run odoo. in my launch.json above the first line is flag from debugpy, then it will run the odoo by specify where the app is, and followed by your odoo configuration. You can find another flag for debugpy in the project repository.

    As for the ${workspaceRoot}, this is the directory you open the workpace on that vscode, say i open this workspace inside directory /opt/odoo, then the ${workspaceRoot} will be /opt/odoo

  4. And now you can run it directly from "Run and Debug" menu, usually this is below the "Search" icon on the left panel

  5. Now you can use the breakpoint feature too, and it will show you the call stack to reach that function from the first method called until paused by the breakpoint.

Run odoo with odoo.conf

Sometimes, when you only use argument, odoo will automatically create default .odoorc, it's better to use separate odoo.conf, especially if you're working on different odoo version or DB

[options]
db_name = False
db_user = odootes
db_password = False
addons_path = addons, odoo/addons, enterprise, custom-addons
list_db = True
dev = all
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment