Method dengan Context pada Kustomisasi Odoo 17

May 11, 2025 | Odoo 17 Development

Pada pemrograman Odoo 17 kita dapat mendefinisikan context ke suatu method. Context ini semacam parameter yang disampaikan ke method.

Method dengan context pada kustomisasi Odoo 17 adalah seperti pada contoh berikut ini

  1. Start SSH file system
  2. Method yang menerima context

    from datetime import datetime, timedelta
    from odoo import  _, fields, models, api
    from odoo.exceptions import UserError
    
    class AsramaStudent(models.Model):
        _name = 'asrama.student'
        _description = 'Informasi Asrama Student'
        partner_id = fields.Many2one('res.partner', ondelete='cascade', delegate=True)
    
        #name = fields.Char('Nama pelajar')
        gender = fields.Selection(
            [('male','Male'),('female','Female'),('other','Other')],
            string='Jenis kelamin',
            help='Jenis kelamin pelajar',
        )
        active = fields.Boolean('Active',default=True,help='Activate/Deactive record')
    
        room_id = fields.Many2one('asrama.room','Room',help='Pilih room')
        hostel_id = fields.Many2one('asrama.hostel',related='room_id.hostel_id')
        
        status = fields.Selection(
            [('draft','Draft'),('reservation','Reservation'),('pending','Pending'),('paid','Paid'),('discharge','Discharge'),('cancel','Cancel')],
            string='Status',copy=False,default='draft',
            help='Status asrama student'
        )
    
        @api.depends('admission_date','discharge_date')
        
        def _compute_check_duration(self):
            """Mengecek durasi"""
            for rec in self:
                if rec.discharge_date and rec.admission_date:
                    rec.duration = (rec.discharge_date - rec.admission_date).days
    
        def _inverse_duration(self):
            for stu in self:
                if stu.discharge_date and stu.admission_date:
                    duration = (stu.discharge_date - stu.admission_date).days
                    if duration != stu.duration:
                        stu.discharge_date = (stu.admission_date + timedelta(days=stu.duration)).strftime('%Y-%m-%d')
                        
        admission_date = fields.Date('Tanggal masuk',help='Tangga di mana pelajar masuk asrama',
            default=fields.Datetime.today())
    
        discharge_date = fields.Date('Tanggal keluar',help='Tanggal di mana pelajar keluar asrama')
    
        duration = fields.Integer('Durasi', compute='_compute_check_duration',inverse='_inverse_duration',
            help='Durasi lamanya tinggal')
        
        def action_assign_room(self):
            self.ensure_one()
            if self.status != 'paid':
                raise UserError(_("Tidak bisa memberikan room jika belum Paid!"))
            room_as_super_user = self.env['asrama.room'].sudo()
            room_rec = room_as_super_user.create({
                'name': 'Kamar A-505',
                'room_no': 'A-505',
                'floor_no': 1,
                'student_per_room' : 5,
                'category_id' : self.env.ref("asramaku.kategori_elite").id,
                'hostel_id': self.hostel_id.id,
            })
    
            if room_rec:
                self.sudo().room_id = room_rec.id
            
        def action_remove_room(self):
            if self.env.context.get('is_hostel_room'):
                self.room_id = False
    
  3. Source code yang memberikan context

    import logging
    from odoo import fields, models, api
    from odoo.exceptions import ValidationError, UserError
    from odoo.tools.translate import _
    
    _logger = logging.getLogger(__name__)
    
    class BaseArchive(models.AbstractModel):
    	_name = 'base.archive'
    	active = fields.Boolean(default=True)
    	
    	def do_archive(self):
    		for record in self:
    			record.active = not record.active
    
    class AsramaRoom(models.Model):
        _name = 'asrama.room'
        _inherit = ['base.archive']
        _description = 'Informasi Kamar Asrama'
        _rec_name = 'room_no'
    
        name = fields.Char('Nama kamar',required=True)
        room_no = fields.Char('No kamar',required=True)
        floor_no = fields.Integer('No Lantai',default=1, help='No Lantai')
        currency_id = fields.Many2one('res.currency',string='Mata uang')
        rent_amount = fields.Monetary('Harga sewa',help='Masukkan harga sewa')
    
        hostel_id = fields.Many2one('asrama.hostel','Hostel', help='Nama hostel')    
    
        student_per_room = fields.Integer('Jml pelajar per kamar',required=True,
            help='Jml yang dialokasikan per kamar')
    
        @api.depends('student_per_room','student_ids')
        def _compute_check_availability(self):
            """Mengecek ketersediaan"""
            for rec in self:
                rec.availability = rec.student_per_room - len (rec.student_ids.ids)
        
        availability = fields.Float(compute='_compute_check_availability',store=True,
            string='Ketersediaan',help='Ketersediaan kamar pada asrama')
    
        student_ids = fields.One2many('asrama.student','room_id','Daftar pelajar',
            help='Pelajar-pelajar dalam room ini')
    
        asrama_amenities_ids = fields.Many2many('asrama.amenities',
            'asrama_amenities_rel','room_id','amenity_id',
            string='Amenities', domain="[('active','=',True)]",
            help='Pilih fasilitas room' 
        )
    
        _sql_constraints = [('room_no_unique','unique(room_no)','Nomor room harus unik!')]
    
        @api.constrains('rent_amount')
        def _check_rent_amount(self):
            """Constraint pada nilai negatif"""
            if self.rent_amount < 0:
                raise ValidationError(_('Nilai rental tidak boleh negatif'))
        
        room_rating = fields.Float('Rata-rata Rating dari Room',digits=(14,4))
     
        state = fields.Selection([
                ('draft','Unavailable'),
                ('available','Available'),
                ('closed','Closed')
            ],
            'State',
            default='draft'
        )
    
        remarks = fields.Text('Remarks')
    
        @api.model
    
        def create(self,values):
            if not self.user_has_groups('base.group_allow_export'):
                if values.get('remarks'):
                    raise UserError('Anda tidak diijinkan membuat remark')
            return super(AsramaRoom, self).create(values)
        
        def write(self,values):
            if not self.user_has_groups('base.group_allow_export'):
                if values.get('remarks'):
                    raise UserError('Anda tidak diijinkan mengubah remark')
            return super(AsramaRoom, self).write(values)
    
        def is_allowed_transition(self,old_state,new_state):
            allowed = [
                 ('draft','available'),
                 ('available','closed'),
                 ('closed','draft')             
            ]
            return (old_state,new_state) in allowed
        
        def change_state(self,new_state):
            for room in self:
                if room.is_allowed_transition(room.state, new_state):
                    room.state = new_state
                else:
                    msg = _('Pindah dari %s ke %s tidak diperbolehkan!') % (room.state,new_state)
                    raise UserError(msg)
    
        def make_available(self):
            self.change_state('available')
        
        def make_closed(self):
            self.change_state('closed')
    
        def log_all_room_members(self):
            asrama_student_obj = self.env['asrama.student']
            all_members = asrama_student_obj.search([])
            print('Semua anggota',all_members)
            return True
        
        def create_categories(self):
            categ1 = {
                'name': 'Child category 1',
                'description': 'Description for child 1'              
            }
            categ2 = {
                'name': 'Child category 2',
                'description':  'Description child 2'
            }
            parent_category_val = {
                'name': 'Parent category',
                'description': 'Description for parent category',
                'child_ids': [
                    (0,0,categ1),
                    (0,0,categ2),
                ]
            }
    
            record = self.env['asrama.category'].create(parent_category_val)
            return True
    
        def update_room_no(self):
            self.ensure_one()
            self.room_no = 'RM2772'
        
        def find_room(self):
            domain = [
                '|',
                    '&',('name','ilike','bunga'),
                        ('hostel_id.name','=','Kemayoran'),
                    '&',('name','ilike','galo'),
                        ('hostel_id.name','=','BSD')
            ]
            rooms = self.search(domain)
            #_logger.info('Room ditemukan %s',rooms)
            print('Room ditemukan %s',rooms)
            return True
    
        def filter_members(self):
            all_rooms = self.search([])
            filtered_rooms = self.rooms_with_multiple_members(all_rooms)
            #_logger.info('Filtered Rooms: %s',filtered_rooms)
            print('Filtered Rooms:', filtered_rooms)
        
        def rooms_with_multiple_members(self, all_rooms):
            def predicate(room):
                if (len(room.student_ids))>1:
                    return True
            return all_rooms.filtered(predicate)
        
        def mapped_rooms(self):
            all_rooms = self.search([])
            room_authors = self.get_member_names(all_rooms)
            #_logger.info('Room Members: %s', room_authors)
            print('Room Members:', room_authors)
            
        def get_member_names(self,all_rooms):
            return all_rooms.mapped('student_ids.name')
        
        def sort_room(self):
            all_rooms = self.search([])
            rooms_sorted = self.sort_by_rent_amount(all_rooms)
            #_logger.info('Rooms before sorting: %s', all_rooms)
            #_logger.info('Rooms after sorting: %s', rooms_sorted)
            print('Rooms before sorting:', all_rooms)
            print('Rooms after sorting:', rooms_sorted)
    
        def sort_by_rent_amount(self,all_rooms):
            return all_rooms.sorted(key='rent_amount')
    
        def average_rent(self):
            avg_result = self.read_group(
                [('rent_amount', '!=', False)],
                ['category_id','rent_amount:avg'],
                ['category_id']
            )
    
            print('Rata-rata harga sewa %s' % (avg_result))
            return True
        
        def action_remove_room_members(self):
            for student in self.student_ids:
                student.with_context(is_hostel_room=True).action_remove_room()
    
  4. View asrama_room

    <?xml version='1.0' encoding='utf-8'?>
    <odoo>
        <!-- asrama.room tree view -->
        <record id="asrama_room_view_tree" model="ir.ui.view">
            <field name="name">asrama.room.view.tree</field>
            <field name="model">asrama.room</field>
            <field name="arch" type="xml">
                <tree string='Room'>
                    <field name="name"/>
                    <field name="room_no" />
                    <field name="floor_no" />
                </tree>
            </field>
        </record>
    
        <!-- asrama.room form view -->
        <record id="asrama_room_view_form" model="ir.ui.view">
            <field name="name">asrama.room.view.form</field>
            <field name="model">asrama.room</field>
            <field name="arch" type="xml">
                <form string="Room">
                    <sheet>
                        <header>
                            <field name="state" widget='statusbar'/>
                        </header>
                        <header>
                            <button name="make_available"  string="Make Available" type="object"/>
                            <button name="make_closed"  string="Make Closed" type="object"/>
                            <button name="log_all_room_members"  string="Log semua kamar members" type="object"/>
                            <button name="average_rent"  string="Rata-rata sewa" type="object"/>
                        </header>
                        <header>
                            <button name="create_categories"  string="Create categories" type="object"/>
                            <button name="update_room_no"  string="Update Room No" type="object"/>
                            <button name="find_room"  string="Find Room" type="object"/>
                            <button name="action_remove_room_members"  string="Remove Room Members" type="object"/>
                        </header>
                        <header>
                            <button name="filter_members"  string="Filter Members" type="object"/>
                            <button name="mapped_rooms"  string="Mapped Rooms" type="object"/>
                            <button name="sort_room"  string="Sort Room" type="object"/>
                        </header>
                        <group>
                            <group description='Kamar'>
                                <field name="name" />
                                <field name="room_no" />
                                <field name="hostel_id" required="1"/>
                                <field name="floor_no" />
                                <field name="active" />
                                <field name="category_id" />
                                <field name="date_terminate" />
                            </group>
                            <group description='Harga'>
                                <field name="student_per_room"/>
                                <field name="availability"/>
                                <field name="rent_amount" />
                                <field name="currency_id" />
                                <field name="remarks" />
                            </group>
                        </group>
                        <notebook>
                            <page name="room_studennt" string="Para Pelajar">
                                <field name="student_ids"/>
                            </page>
                            <page name="asrama_amenities" string="Room Amenities">
                                <group>
                                    <field name="asrama_amenities_ids" widget="many2many_tags"/>
                                </group>
                            </page>
                        </notebook>
                    </sheet>
                </form>
            </field>
        </record>
    
        <!-- asrama.room action window -->
        <record id="asrama_room_action" model="ir.actions.act_window">
            <field name="name">Room</field>
            <field name="type">ir.actions.act_window</field>
            <field name="res_model">asrama.room</field>
            <field name="view_mode">tree,form</field>
            <field name="domain">[]</field>
            <field name="context">{}</field>
            <field name="help" type="html">
                <p class="oe_view_nocontent_create">
                    Tambah kamar
                </p>
            </field>
        </record>
    
        <!-- This Menu Item must have a parent and an action -->
        <menuitem id="asrama_room_menu" name="Room Asrama" parent="hostel_main_menu" action="asrama_room_action" sequence="2"/>
    
    </odoo>
    

  5. Start Odoo dengan upgrade modul
  6. Klik tombol
  7. Hasil

Kunjungi www.proweb.co.id/implementasi-odoo/ jika anda membutuhkan layanan mplementasi Odoo ERP.