Skip to content

This is my opensource module for making Real State Module. Here I implement odoo docs beginner tutorial in estate and estate_account and also advanced topics in property and property_account

Notifications You must be signed in to change notification settings

bushmusi/odoo-real-state-module

Repository files navigation

Odoo Real State module

Tutorial https://www.odoo.com/documentation/11.0/howtos/backend.html

VCode plugins

  • Python
  • XML Tools

Resources

Deploy

Docker

Module

Scaffolding

$ odoo-bin scaffold openacademy addons

Add custon addons path

  • Go to location: /etc/odoo/odoo-server.conf
  • Add path in that file: addons_path = /opt/odoo/enterprise,/opt/odoo/addons,/opt/odoo/custom-addons
$ ./odoo-bin --addons-path=enterprise/,../custom-addons/,../odoo/addons/
my_module
├── __init__.py
├── __manifest__.py
├── controllers
│   ├── __init__.py
│   └── controllers.py
├── demo
│   └── demo.xml
├── models
│   ├── __init__.py
│   └── models.py
├── security
│   └── ir.model.access.csv
└── views
    ├── templates.xml
    └── views.xml

Manifest

manifest.py

The manifest ofthe module, including for instance its title, description and data files to load.

{ 
    'name': "Title", 
    'summary': "Short subtitle phrase", 
    'description': """Long description""", 
    'author': "Your name", 
    'license': "AGPL-3", 
    'website': "http://www.example.com", 
    'category': 'Uncategorized', 
    'version': '11.0.1.0.0', 
    'depends': ['base'], 
    'data': ['views.xml'], 
    'demo': ['demo.xml'], 
}

Module

Module

Module

Models

models/models.py

Business objects are declared as Python classes extending Model which integrates them into the automated persistence system. Models can be configured by setting a number of attributes at their definition.

    # Strings
    name = fields.Char(string="Title", required=True)
    description = fields.Text()

    # Date
    start_date = fields.Date()
    start_datetime = fields.Datetime('Start time', default=lambda self: fields.Datetime.now())
    
    # Numbers
    duration = fields.Float(digits=(6, 2), help="Duration in days")
    seats = fields.Integer(string="Number of seats")
    active = fields.Boolean(default=True) # Boolena

    # Relational fields
    responsible_id = fields.Many2one('res.users', ondelete='set null', string="Responsible", index=True)
    instructor_id = fields.Many2one('res.partner', string="Instructor")
    course_id = fields.Many2one('openacademy.course', ondelete='cascade', string="Course", required=True)
    session_ids = fields.One2many('openacademy.session', 'course_id', string="Sessions")

When a new fields are adding is necessary to restart Odoo and upgrading the module.

$ service odoo restart

Computed fields

    taken_seats = fields.Float(string="Taken seats", compute='_taken_seats')

    @api.depends('seats', 'attendee_ids')
    def _taken_seats(self):
        for r in self:
            if not r.seats:
                r.taken_seats = 0.0
            else:
                r.taken_seats = 100.0 * len(r.attendee_ids) / r.seats

Inheritance

# -*- coding: utf-8 -*-
from odoo import fields, models

class Partner(models.Model):
    _inherit = 'res.partner'

    # Add a new column to the res.partner model, by default partners are not
    # instructors
    instructor = fields.Boolean("Instructor", default=False)

    session_ids = fields.Many2many('openacademy.session',
        string="Attended Sessions", readonly=True)

Onchange

The “onchange” mechanism provides a way for the client interface to update a form whenever the user has filled in a value in a field, without saving anything to the database.

    @api.onchange('seats', 'attendee_ids')
    def _verify_valid_seats(self):
        if self.seats < 0:
            return {
                'warning': {
                    'title': "Incorrect 'seats' value",
                    'message': "The number of available seats may not be negative",
                },
            }
        if self.seats < len(self.attendee_ids):
            return {
                'warning': {
                    'title': "Too many attendees",
                    'message': "Increase seats or remove excess attendees",
                },
            }

Constrains

  • Python constraints
  • SQL constraints
from odoo import models, fields, api, exceptions

....

    @api.constrains('instructor_id', 'attendee_ids')
    def _check_instructor_not_in_attendees(self):
        for r in self:
            if r.instructor_id and r.instructor_id in r.attendee_ids:
                raise exceptions.ValidationError("A session's instructor can't be an attendee")

Views

views/views.xml

Tree and a form views, with the menus opening them. Actions and menus are regular records in database, usually declared through data files. Actions can be triggered in three ways:

  • by clicking on menu items (linked to specific actions)
  • by clicking on buttons in views (if these are connected to actions)
  • as contextual actions on object

*Basics views

  • Tree views . List views, display records in a tabular form.
  • Form views . Forms are used to create and edit single records.
  • Search views . Search views customize the search field associated with the list view (and other aggregated views).

Adding in manifest.py

    # always loaded
    'data': [
        # 'security/ir.model.access.csv',
        # 'views/views.xml',
        'views/templates.xml',
        'views/openacademy.xml',
        'views/partner.xml',
        'reports.xml',

    ],

Menus and actions

<record model="ir.actions.act_window" id="course_list_action">
        <field name="name">Cursos</field>
        <field name="res_model">openacademy.course</field>
        <field name="view_type">form</field>
        <field name="view_mode">tree,form</field>
        <!-- Personalización de Búsquedas -->
        <field name="context" eval="{'search_default_my_courses': 1}"/>
        <field name="help" type="html">
            <p class="oe_view_nocontent_create">Crea el primer curso
            </p>
        </field>
    </record>

    <!-- top level menu: no parent -->
    <menuitem id="main_openacademy_menu" name="Open Academy"/>
    <!-- A first level in the left side menu is needed before using action= attribute -->
    <menuitem id="openacademy_menu" name="Open Academy" parent="main_openacademy_menu"/>
    <!-- the following menuitem should appear *after* its parent openacademy_menu and *after* its
             action course_list_action -->
    <menuitem id="courses_menu" name="Courses" parent="openacademy_menu" action="course_list_action"/>
    <!-- Full id location: action="openacademy.course_list_action"  It is not required when it is the same module -->

Module

Tree views

    <record model="ir.ui.view" id="course_tree_view">
        <field name="name">course.tree</field>
        <field name="model">openacademy.course</field>
        <field name="arch" type="xml">
            <tree string="Course Tree">
                <field name="name"/>
                <field name="responsible_id"/>
            </tree>
        </field>
    </record>

Module

Module

Form views

    <!-- Sesión Formulario -->
    <record model="ir.ui.view" id="session_form_view">
        <field name="name">session.form</field>
        <field name="model">openacademy.session</field>
        <field name="arch" type="xml">
            <form string="Session Form">
                <sheet>
                    <group>
                        <group string="General">
                            <field name="course_id"/>
                            <field name="name"/>
                            <field name="instructor_id"/>
                            <field name="active"/>
                        </group>
                        <group string="Schedule">
                            <field name="start_date"/>
                            <field name="duration"/>
                            <field name="seats"/>
                            <!-- Computed fields -->
                            <field name="taken_seats" widget="progressbar"/>
                        </group>
                    </group>
                    <label for="attendee_ids"/>
                    <field name="attendee_ids"/>
                </sheet>
            </form>
        </field>
    </record>

Module

Search views

    <record model="ir.ui.view" id="course_search_view">
        <field name="name">course.search</field>
        <field name="model">openacademy.course</field>
        <field name="arch" type="xml">
            <search>
                <field name="name"/>
                <field name="description"/>
                <!-- Advanced search-->
                <filter name="my_courses" string="My Courses" domain="[('responsible_id', '=', uid)]"/>
                <group string="Group By">
                    <filter name="by_responsible" string="Responsible" context="{'group_by': 'responsible_id'}"/>
                </group>

            </search>
        </field>
    </record>

Module

Module

Calendar

Module

Graph

Module

Report

<odoo>

    <report
        id="report_session"
        model="openacademy.session"
        string="Session Report"
        name="openacademy.report_session_view"
        file="openacademy.report_session"
        report_type="qweb-pdf" />

    <template id="report_session_view">
        <t t-call="web.html_container">
            <t t-foreach="docs" t-as="doc">
                <t t-call="web.external_layout">
                    <div class="page">
                        <h2 t-field="doc.name"/>
                        <p>From <span t-field="doc.start_date"/> to <span t-field="doc.end_date"/></p>
                        <h3>Attendees:</h3>
                        <ul>
                            <t t-foreach="doc.attendee_ids" t-as="attendee">
                                <li><span t-field="attendee.name"/></li>
                            </t>
                        </ul>
                    </div>
                </t>
            </t>
        </t>
    </template>

</odoo>

Module

Controllers

controllers/controllers.py

Demos

demo/demo.xml, demo records for the above example model

Define demonstration data. The content of the data files is only loaded when a module is installed or updated.After making some changes, do not forget to use odoo-bin -u openacademy to save the changes to your database.

Security

Links

About

This is my opensource module for making Real State Module. Here I implement odoo docs beginner tutorial in estate and estate_account and also advanced topics in property and property_account

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published