How to create custom addons in odoo 14

Custom modules can be used to organize or display content in ways not possible using the default Participate content modules. For example, you can create a module that uses more fields than those allowed in the standard content modules

Now we need to know how to create a custom module in odoo 14 .

1: Open pycharm go to custom addons , right click , click new,click directory add your module name (eg:enzapps).

2: Right click on that module click new directory and name as(models).

3: Right click on created models,click new python file,click file name as(__init__.py) and create another new python files and give name ur python file(enzapps_estimate.py) and create one new class on that py file and add needed fields

syntax:

class ClassName(models.Model):

_name=’class.name’

field_name=fields.Type(“String”)

practical case:

class EstimateContract(models.Model):

_name=’estimate.contract’

p_type = fields.Many2one('res.partner')
location = fields.Char('') address = fields.Text()
furnishing = fields.Selection(selection=[('yes', 'YES'), ('no', 'NO')])
expected_date = fields.Date()
created_date = fields.Datetime()
currency = fields.Selection(selection=[('usd', 'USD'), ('inr', 'INR')])
area_of_building = fields.Float()
budget = fields.Integer()
etc..

Note: While creating any python file you need to add  first line as

from odoo import models,fields,api

4: In __init__.py add all python files names created under the “models” (eg: from . import enzapps_estimate)

5: Right click on that module( enzapps) ,click new,click directory name as (views).

6: Right click on views ,click new file , give name your xml file (eg:enzapps_estimate.xml). and

Add  following sections such as;  one record for showing fields and another record for menu action and another section for button

<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<!-- To show fields, here change record id and model name-->
  <record id="enzapps_contract_form_id" model="ir.ui.view">
      <field name="name">estimate.enzapps.form</field>
      <field name="model">estimate.contract</field>
      <field name="arch" type="xml">
          <form>
              <sheet>
                  <group>
                      <group>

                          <field name="p_type"/>
                          <field name="address"/>
                          <field name="furnishing"/>
                          <field name="expected_date"/>
                          <field name="created_date"/>
                      </group>
                      <group>
                          <field name="location"/>
                          <field name="currency"/>
                          <field name="area_of_building"/>
                          <field name="area_of_building"/>
                          <field name="budget"/>
                      </group>
                  </group>

              </sheet>
          </form>
      </field>
  </record>
<!--    To show action menu , here change record id and model name-->
   <record id="enzapps_contact_action" model="ir.actions.act_window">
        <field name="name">Estimate Order</field>
        <field name="res_model">estimate.contract</field>
        <field name="view_mode">tree,form</field>
        <field name="help" type="html">
            <p class="oe_view_nocontent_create">
                No contract available
            </p>
        </field>
    </record>
<!--    To show menu, here action record id should be same as this menuitem action-->
    <menuitem id="enzapps_contract"
              name="Enzapps Contract"
              sequence="1"
              action="enzapps_contact_action"/>

</odoo>

7: Right click on that module( enzapps) ,click new directory name as(security).

8: Right click on security and new file name as (ir.model.access.csv).

9: Open csv file add

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink

access_your class_name,your class.name,model_class_name,base.group_user,1,1,1,1

Here keep first line as it is and change second line with class name,  second line as example as follows

eg:access_enzapps_estimate,enzapps.estimate,model_enzapps_estimate,base.group_user,1,1,1,1

Note: try Till Now  what we did correct or not  by doing point 13 , 14 and 15 after this try to install the module it will be look like this

10: Right click on module then go to new directory name as(report).

11: Right click on report, add new file name as (report.xml) . and add following details

<?xml version="1.0" encoding="UTF-8"?>
<odoo>
    <report id="enzapps_estimate_id"
          model="estimate.contract"
          string=" Enzapps Estimate "
          report_type="qweb-pdf"
          name="enzapps.enzapps_contract_body_format"
          file="enzapps.enzapps_contract_body_format"/>
<!--    name and file should be custom addon name . body template id from corresponding xml file-->
<!--   model should be our class name-->
    </odoo>

12: Right click on reports and new file, give all ur reports names(eg:enzapps_estimate_view.xml).  and add this code

<?xml version="1.0" encoding="UTF-8" ?>

<odoo>
<!--    here you need to change header template_id as your wish-->
    <template id="enzapps_ccontract_header_format">
        <t t-call="web.html_container">
            <t t-if="not o" t-set="o" t-value="doc"/>
            <t t-if="not company">
                <!--  Multicompany  -->
                <t t-if="company_id">
                    <t t-set="company" t-value="company_id"/>
                </t>
                <t t-elif="o and 'company_id' in o">
                    <t t-set="company" t-value="o.company_id.sudo()"/>
                </t>
                <t t-else="else">
                    <t t-set="company" t-value="res_company"/>
                </t>
            </t>
            <div class="header" t-att-style="report_header_style">
                <div class="row">
                </div>
            </div>
            <div class="col-9 text-right" t-field="company.report_header" name="moto">
                <div t-field="company.partner_id" t-options="{&quot;widget&quot;: &quot;contact&quot;, &quot;fields&quot;: [&quot;address&quot;, &quot;name&quot;], &quot;no_marker&quot;: true}"/>
            </div>
            <div class="article" t-att-data-oe-model="o and o._name" t-att-data-oe-id="o and o.id" t-att-data-oe-lang="o and o.env.context.get('lang')">
                <t t-raw="0"/>
            </div>
            <div class="footer o_background_footer">
                <div>
                    <div t-field="company.report_footer"/>
                    <div t-if="report_type == 'pdf'" class="text-muted">
                        <hr style="width:100%;" color="red"/>
                        <div class="row">
                            <div class="col-6" style="text-align:right;">
                                Page:
                                <span class="page"/>
                                /
                                <span class="topage"/>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </t>
    </template>
<!--    here we need to change body  template_id as you wish-->
<!-- this body template should give in report.xml as name and file-->

    <template id="enzapps_contract_body_format">
        <t t-call="web.html_container">
            <t t-foreach="docs" t-as="o">
<!--                here we have to change <t t-call=module name.header template_id-->
                <t t-call="enzapps.enzapps_ccontract_header_format">
                    <div class="page">
<!--                        Here we have to change the report design as you wish-->
                    <table style="border:1px solid black;width:100%">
                        <tr>
                            <td>P Type</td>
                            <td><t t-esc="o.p_type.name"/></td>
                            <td>Location</td>
                            <td><t t-esc="o.location"/></td>
                        </tr>
                        <tr>
                            <td>Address</td>
                            <td><t t-esc="o.address"/> </td>
                            <td>Currency</td>
                            <td><t t-esc="o.currency"/> </td>
                        </tr>
                        <tr>
                            <td>Furnishing</td>
                            <td><t t-esc="o.furnishing"/> </td>
                            <td>Area of building</td>
                            <td><t t-esc="o.area_of_building"/> </td>
                        </tr>
                        <tr>
                            <td>Expexted Date</td>
                            <td><t t-esc="o.expected_date"/> </td>
                            <td>Area of building</td>
                            <td><t t-esc="o.area_of_building"/> </td>
                        </tr>
                        <tr>
                            <td>Created Date</td>
                            <td><t t-esc="o.created_date"/> </td>
                            <td>Budget</td>
                            <td><t t-esc="o.budget"/> </td>
                        </tr>
                    </table>
                        <p style="page-break-after:always;"> </p>
                        <h2 style="text-align:center">Test Page</h2>
                    </div>
                </t>
            </t>
        </t>
    </template>
</odoo>     

after this u can update manifest file by uncommenting report field as follows
'report/report.xml',
'report/enzapps_estimate_view.xml'
run  pycharam The print will be like this  

 

13: Right click on module ( enzapps) new file name as(__init__.py)

14: Inside the __init__.py file write as (from . import models)

15: Then right click on module ( building_contract) new file name as (__manifest__.py).

16: Inside manifest mansatory to include security file,views,and reports.

Note: if you are doing point 11 and 12 please uncomment manifest file ‘report/report.xml’ and report/enzapps_report_view.xml’

 

{
    'name': "Enzapps Contract",
    'author':
        'ENZAPPS',
    'summary': """
TO manage contarct.
""",
    'description': """
        This module is for entry of building dara
    """,
    'website': "www.enzapps.com",
    'category': 'base',
    'version': '14.0',
    'depends': ['base'],
    #"images": ['static/description/icon.png'],
    'data': [
        'security/ir.model.access.csv',
        'views/enzapps_estimate.xml',
        # 'report/report.xml',
        # 'report/estimate_view.xml'
    ],
    'demo': [
    ],
    'installable': True,
    'application': True,
}



To know more about us

Additional features (1)

Right now while running module, it will work properly, if you want to change the 
view type while opening menu, u can add a record to show  tree view in
 enzapps_estimate.xml, as follows

<record id="enzapps_contract_tree_view" model="ir.ui.view">
    <field name="name">enzapps.estimate</field>
    <field name="model">estimate.contract</field>
    <field name="arch" type="xml">
        <tree>
                      <field name="p_type"/>
                      <field name="address"/>
                      <field name="furnishing"/>
                      <field name="expected_date"/>
                      <field name="created_date"/>
                      <field name="location"/>
                      <field name="currency"/>
                      <field name="area_of_building"/>
                      <field name="area_of_building"/>
                      <field name="budget"/>
        </tree>
    </field>
</record>

Result will be as follows:


Additional features(2) 

If you want to add One2Many for more product details for your form, you can add one field 
with type One2Many in existing class(estimate_contract.py) and create new class and add fields 
in new class
syntax:
from odoo import models,fields,api


class EnzappasEstimate(models.Model):
    _name='estimate.contract'




    # name_seq=fields.Char(string="Sequence No", readonly=True, required=True, copy=False, default='new')
    p_type = fields.Many2one('res.partner')
    location = fields.Char()
    address = fields.Text()
    furnishing = fields.Selection(selection=[('yes', 'YES'), ('no', 'NO')])
    expected_date = fields.Date()
    created_date = fields.Datetime()
    currency = fields.Selection(selection=[('usd', 'USD'), ('inr', 'INR')])
    area_of_building = fields.Float()
    budget = fields.Integer()

 # This is the field we mentioned  One2Many, add this line in existing class

    order_lines = fields.One2many('enzapps.estimate.line', 'connection')




class enzappsEstimateLineLines(models.Model):
        _name = 'enzapps.estimate.line'

        connection = fields.Many2one('estimate.contract')
        product_id = fields.Many2one('product.product', 'Product')
        quantity = fields.Float()
        unit_price = fields.Float()
        total_price = fields.Float()

        # price_subtotal = fields.Monetary()
        @api.onchange('quantity', 'unit_price')
        def total(self):
            self.total_price = self.quantity * self.unit_price 

Then you can create corresponding xml file, we can create notbook for One2many
in corresponding xml file, you have to add one notebook after closing group.here 
u can find full xml format below, from that u can copy notepbook session and paste
iin xml file.

Syntax as follows:
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<!-- To show fields-->
    <record id="enzapps_contract_tree_view" model="ir.ui.view">
        <field name="name">enzapps.estimate</field>
        <field name="model">enzapps.estimate</field>
        <field name="arch" type="xml">
            <tree>
                          <field name="p_type"/>
                          <field name="address"/>
                          <field name="furnishing"/>
                          <field name="expected_date"/>
                          <field name="created_date"/>
                          <field name="location"/>
                          <field name="currency"/>
                          <field name="area_of_building"/>
                          <field name="area_of_building"/>
                          <field name="budget"/>
            </tree>
        </field>
    </record>
  <record id="enzapps_contract_form_id" model="ir.ui.view">
      <field name="name">estimate.enzapps.form</field>
      <field name="model">enzapps.estimate</field>
      <field name="arch" type="xml">
          <form>
              <sheet>
                  <group>
                      <group>

                          <field name="p_type"/>
                          <field name="address"/>
                          <field name="furnishing"/>
                          <field name="expected_date"/>
                          <field name="created_date"/>
                      </group>
                      <group>
                          <field name="location"/>
                          <field name="currency"/>
                          <field name="area_of_building"/>
                          <field name="area_of_building"/>
                          <field name="budget"/>
                      </group>
                  </group>
<!--                  This for One2many, copy this andpaste existing xml-->
                  <notebook>
                      <page string="Estimate">
                          <field name="order_lines">
                              <tree string="Statement lines" editable="bottom">
                                  <field name="product_id"/>
                                  <field name="quantity"/>
                                  <field name="unit_price"/>
                                  <field name="total_price"/>
                              </tree>
                          </field>
                      </page>
                  </notebook>

              </sheet>
          </form>
      </field>
  </record>

    <!--    To show action menu-->
   <record id="enzapps_contact_action" model="ir.actions.act_window">
        <field name="name">Estimate Order</field>
        <field name="res_model">enzapps.estimate</field>
        <field name="view_mode">tree,form</field>
        <field name="help" type="html">
            <p class="oe_view_nocontent_create">
                No contract available
            </p>
        </field>
    </record>
<!--    To show menu-->
    <menuitem id="enzapps_contract"
              name="Enzapps Contract"
              sequence="1"
              action="enzapps_contact_action"/>

</odoo>
  

Then it shows Like this:


Note: dont forget to add the New created class in our security file and 
add related field in xml file as table.

syntax as follows. add following codes after table tag ,
<table style="border:1px solid black;width:100%">
    <tr>
        <td style="border:1px solid black">Sn</td>
        <td style="border:1px solid black">Product</td>
        <td style="border:1px solid black">Quantity</td>
        <td style="border:1px solid black">Unit Price</td>
        <td style="border:1px solid black">Total Price</td>
    </tr>
    <t t-set="i" t-value="1"/>
    <t t-foreach="o.order_lines" t-as="one_to_many">
        <tr>
            <td style="border:1px solid black"><t t-esc="i"/></td>
            <td style="border:1px solid black"><t t-esc="one_to_many.product_id.name"/> </td>
            <td style="border:1px solid black"><t t-esc="one_to_many.quantity"/></td>
            <td style="border:1px solid black"><t t-esc="one_to_many.unit_price"/></td>
            <td style="border:1px solid black"><t t-esc="one_to_many.total_price"/></td>
        </tr>
        <t t-set="i" t-value="i+1"/>
    </t>
</table>
output will be like below

		

Leave a Reply

Your email address will not be published.