diff --git a/estate/__init__.py b/estate/__init__.py
new file mode 100644
index 00000000000..d4c3532319d
--- /dev/null
+++ b/estate/__init__.py
@@ -0,0 +1,3 @@
+from . import wizards
+from . import controllers
+from . import models
diff --git a/estate/__manifest__.py b/estate/__manifest__.py
new file mode 100644
index 00000000000..007b1432dd6
--- /dev/null
+++ b/estate/__manifest__.py
@@ -0,0 +1,31 @@
+{
+    'name': "Real State",
+    'depends': ['base', 'website'],
+    'author': "Sahil Mangukiya",
+    'category': 'Real Estate/Brokerage',
+    'description': "This is my First tutorial module.",
+    'data': [
+        'security/estate_security.xml',
+        'security/ir.model.access.csv',
+        'data/estate.property.type.csv',
+        'reports/estate_property_website_template.xml',
+        'reports/estate_property_detail_template.xml',
+        'reports/print_offer_table_subtemplate.xml',
+        'reports/estate_property_offer_report_template.xml',
+        'reports/estate_salesman_property_offer_report_template.xml',
+        'reports/estate_property_reports.xml',
+        'views/res_users_views.xml',
+        'wizards/add_offer.xml',
+        'views/estate_property_offer_views.xml',
+        'views/estate_property_type_views.xml',
+        'views/estate_property_tag_views.xml',
+        'views/estate_property_views.xml',
+        'views/estate_menu.xml'
+    ],
+    'demo': [
+        'demo/estate_property_demo.xml',
+    ],
+    'installable': True,
+    'application': True,
+    'auto_install': False
+}
diff --git a/estate/controllers/__init__.py b/estate/controllers/__init__.py
new file mode 100644
index 00000000000..c5ba8c48107
--- /dev/null
+++ b/estate/controllers/__init__.py
@@ -0,0 +1 @@
+from . import property_website
diff --git a/estate/controllers/property_website.py b/estate/controllers/property_website.py
new file mode 100644
index 00000000000..12d35aa865d
--- /dev/null
+++ b/estate/controllers/property_website.py
@@ -0,0 +1,39 @@
+from odoo import http
+from odoo.http import request
+
+from odoo.addons.portal.controllers.portal import pager as portal_pager 
+
+
+class propertyWebsiteController(http.Controller):
+
+    @http.route(['/properties', '/properties/page/<int:page>'], website=True, auth='public', type='http')
+    def property_website(self, page=1, **kwargs):
+        property_limit_per_page = 6
+        property_count = request.env["estate.property"].sudo().search_count(
+            domain=[('state','in',('new', 'offer received', 'offer accepted')), ('active', '=', True)]
+        )
+        pager = portal_pager(
+            url="/properties",
+            total=property_count,
+            page=page,
+            step=property_limit_per_page
+        )
+        property = request.env["estate.property"].sudo().search(
+            domain=[('state','in',('new', 'offer received', 'offer accepted')), ('active', '=', True)],
+            offset=pager['offset'],
+            limit=property_limit_per_page
+        )
+        return request.render('estate.estate_property_website_template', 
+        {
+            'properties': property,
+            'pager': pager
+        })
+    
+
+    @http.route('/property/<int:property_id>', website=True, auth='public', type='http')
+    def property_detail_view(self, property_id):
+        property = request.env['estate.property'].sudo().browse(property_id)
+        return request.render('estate.estate_property_detail_template',
+        {
+            'property' : property,
+        })
diff --git a/estate/data/estate.property.type.csv b/estate/data/estate.property.type.csv
new file mode 100644
index 00000000000..2dba79266ca
--- /dev/null
+++ b/estate/data/estate.property.type.csv
@@ -0,0 +1,5 @@
+id,name
+1,"Residential"
+2,"Commercial"
+3,"Industrial"
+4,"Land"
diff --git a/estate/demo/estate_property_demo.xml b/estate/demo/estate_property_demo.xml
new file mode 100644
index 00000000000..bad0fc8989c
--- /dev/null
+++ b/estate/demo/estate_property_demo.xml
@@ -0,0 +1,121 @@
+<odoo>
+    <data>
+        <record id="id1" model="estate.property">
+            <field name="name">Big villa</field>
+            <field name="state">new</field>
+            <field name="description">A nice and big villa</field>
+            <field name="postcode">12345</field>
+            <field name="data_availability">2020-02-02</field>
+            <field name="expected_price">1600000</field>
+            <field name="bedrooms">6</field>
+            <field name="living_area">100</field>
+            <field name="facades">4</field>
+            <field name="garage">True</field>
+            <field name="garden">True</field>
+            <field name="garden_area">100000</field>
+            <field name="garden_orientation">south</field>
+            <field name="property_type_id" ref="1"/>
+        </record>
+
+        <record id="id2" model="estate.property">
+            <field name="name">Trailer home</field>
+            <field name="state">cancelled</field>
+            <field name="description">Home in a trailer park</field>
+            <field name="postcode">54321</field>
+            <field name="data_availability">1970-01-01</field>
+            <field name="expected_price">100000</field>
+            <field name="selling_price">120000</field>
+            <field name="bedrooms">1</field>
+            <field name="living_area">10</field>
+            <field name="facades">4</field>
+            <field name="garage">False</field>
+            <field name="property_type_id" ref="1"/>
+        </record>
+
+        <record id="id3" model="estate.property">
+            <field name="name">Sahil's Land</field>
+            <field name="state">new</field>
+            <field name="description">This is my land, Don't play cricket!!</field>
+            <field name="postcode">12345</field>
+            <field name="data_availability">2020-02-02</field>
+            <field name="expected_price">100</field>
+            <field name="bedrooms">30</field>
+            <field name="living_area">100</field>
+            <field name="facades">4</field>
+            <field name="garage">True</field>
+            <field name="garden">True</field>
+            <field name="garden_area">100000</field>
+            <field name="garden_orientation">south</field>
+            <field name="property_type_id" ref="4"/>
+            <field name="offer_ids" eval="[
+                Command.create({
+                    'partner_id': ref('base.res_partner_12'),
+                    'price': 92,
+                    'validity': 100
+                }),
+                Command.create({
+                    'partner_id': ref('base.res_partner_2'),
+                    'price': 94,
+                    'validity': 100
+            })]"/>
+        </record>
+
+        <record id="offer_1" model="estate.property.offer">
+            <field name="partner_id" ref="base.res_partner_12"/>
+            <field name="price">1600000</field>
+            <field name="property_id" ref="id1"/>
+            <field name="validity">14</field>
+        </record>
+
+        <record id="offer_2" model="estate.property.offer">
+            <field name="partner_id" ref="base.res_partner_12"/>
+            <field name="price">1600001</field>
+            <field name="property_id" ref="id1"/>
+            <field name="validity">14</field>
+        </record>
+
+        <record id="offer_3" model="estate.property.offer">
+            <field name="partner_id" ref="base.res_partner_2"/>
+            <field name="price">1600002</field>
+            <field name="property_id" ref="id1"/>
+            <field name="validity">14</field>
+        </record>
+
+        <record id="offer_4" model="estate.property.offer">
+            <field name="partner_id" ref="base.res_partner_2"/>
+            <field name="price">100001</field>
+            <field name="property_id" ref="id2"/>
+            <field name="validity">7</field>
+        </record>
+
+        <record id="offer_5" model="estate.property.offer">
+            <field name="partner_id" ref="base.res_partner_12"/>
+            <field name="price">100002</field>
+            <field name="property_id" ref="id2"/>
+            <field name="validity">7</field>
+            
+        </record>
+        
+        <function model="estate.property.offer" name="action_accept">
+            <value eval="[ref('offer_1')]"/>
+        </function>
+
+        <function model="estate.property.offer" name="action_refuse">
+            <value eval="[ref('offer_2')]"/>
+        </function>
+
+        <function model="estate.property.offer" name="action_refuse">
+            <value eval="[ref('offer_3')]"/>
+        </function>
+
+        <function model="estate.property.offer" name="action_accept">
+            <value eval="[ref('offer_4')]"/>
+        </function>
+
+        <function model="estate.property.offer" name="action_refuse">
+            <value eval="[ref('offer_5')]"/>
+        </function>
+
+    </data>
+       
+</odoo>
diff --git a/estate/models/__init__.py b/estate/models/__init__.py
new file mode 100644
index 00000000000..9a2189b6382
--- /dev/null
+++ b/estate/models/__init__.py
@@ -0,0 +1,5 @@
+from . import estate_property
+from . import estate_property_type
+from . import estate_property_tag
+from . import estate_property_offer
+from . import res_users
diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py
new file mode 100644
index 00000000000..541c3b5e08e
--- /dev/null
+++ b/estate/models/estate_property.py
@@ -0,0 +1,98 @@
+from datetime import timedelta
+
+from odoo import models, fields, api
+from odoo.exceptions import UserError, ValidationError
+
+
+class estateProperty(models.Model):
+        _name = "estate.property"
+        _description = "This is property Table."
+        _order = "selling_price desc, name"
+
+        name = fields.Char(required=True)
+        description = fields.Text()
+        postcode = fields.Char()
+        data_availability = fields.Date(default=lambda self: fields.Date.today() + timedelta(days=90), copy=False)
+        expected_price = fields.Float(required=True)
+        selling_price = fields.Float(readonly=True, copy=False)
+        bedrooms = fields.Integer(change_default=True)
+        living_area = fields.Integer()
+        facades = fields.Integer()
+        garage = fields.Boolean()
+        garden = fields.Boolean()
+        garden_area = fields.Integer()
+        garden_orientation = fields.Selection(
+            string='Orientation',
+            selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')],
+            help="Garden Orientation is avialable in four faces of direction."
+        )
+        active = fields.Boolean(default=True)
+        state = fields.Selection(
+            string='State',
+            selection=[('new', 'New'), ('offer received', 'Offer Received'), ('offer accepted', 'Offer Accepted'), ('sold', 'Sold'), ('cancelled', 'Cancelled')],
+            help="Offer available in five type.",
+            required=True,
+            copy=False,
+            default='new'
+        )
+        number = fields.Integer(related='property_type_id.number')
+        totalArea = fields.Integer(compute='_compute_total_area', store="true")
+        best_offer = fields.Float(compute='_compute_best_offer')
+        property_image = fields.Binary()
+
+        property_type_id = fields.Many2one(comodel_name='estate.property.type', string='Property Type', domain="[('number', '>=', 0)]", ondelete='cascade')
+        seller_id = fields.Many2one('res.users', 'Salesman', default=lambda self: self.env.user)
+        buyer_id = fields.Many2one('res.partner', 'Buyer')
+        tag_ids = fields.Many2many(comodel_name='estate.property.tag', string='Tag', relation='property_join_tag', column1='property_id', column2='tag_id')
+        offer_ids = fields.One2many('estate.property.offer', 'property_id')
+        company_id = fields.Many2one('res.company', required=True, default=lambda self: self.env.company)
+
+
+        _sql_constraints = [
+                ('check_selling_price', 'CHECK(selling_price >= 0)', 'A property selling price must be positive.'), 
+                ('check_expected_price', 'CHECK(expected_price > 0)', 'A property expected price must be strictly positive.')
+        ]
+
+        @api.depends('garden_area', 'living_area')
+        def _compute_total_area(self):
+                for record in self:
+                        record.totalArea = record.garden_area + record.living_area
+
+        @api.depends('offer_ids.price')
+        def _compute_best_offer(self):
+                for record in self:
+                        if record.offer_ids:
+                                record.best_offer = max(record.offer_ids.mapped('price'))
+                        else:
+                                record.best_offer = 0.0
+
+        @api.onchange('garden')
+        def _onchange_garden(self):
+                if self.garden:
+                        self.garden_area = 10
+                        self.garden_orientation = 'north'
+                else:
+                        self.garden_area = 0
+                        self.garden_orientation = False
+
+        def action_sold(self):
+                if(self.state == 'cancelled'):
+                        raise UserError("You can not mark a cancelled property as sold.")
+                self.state = 'sold'
+        
+        def action_cancelled(self):
+                if(self.state == 'sold'):
+                        raise UserError("You can not mark sold property as cancelled")
+                self.state = 'cancelled'
+
+        @api.constrains('selling_price', 'expected_price')
+        def _check_selling_price(self):
+                for record in self:
+                        if record.selling_price < (0.9 * record.expected_price) and (record.selling_price > 0):
+                               raise ValidationError("Selling price cannot be lower than 90 percentage of the expected price.")
+
+        @api.ondelete(at_uninstall=False)
+        def _prevent_delete(self):
+                for record in self:
+                        if record.state not in ("new", "cancelled"):
+                                raise UserError("You can not delete a property which are in offer received, offer accepted or sold state.")
diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py
new file mode 100644
index 00000000000..bc4c718767b
--- /dev/null
+++ b/estate/models/estate_property_offer.py
@@ -0,0 +1,78 @@
+from datetime import timedelta, datetime
+
+from odoo import models, fields, api
+from odoo.exceptions import UserError
+
+
+class estatePropertyOffer(models.Model):
+
+    _name = "estate.property.offer"
+    _description = "This is offer table"
+    _order = "id desc"
+
+    price = fields.Float(required=True)
+    status = fields.Selection(string='Status', selection=[('accepted', 'Accepted'), ('refused', 'Refused')])
+    validity = fields.Integer(default=7, string="Validity")
+    date_deadline = fields.Date(compute='_compute_deadline', inverse='_inverse_deadline', string="Date Deadline")
+    sum = fields.Integer(compute='_compute_sum', string="Sum")
+    sum2 = fields.Integer(compute='_compute_sum2', string="Sum2")
+
+    partner_id = fields.Many2one('res.partner', string='Buyer', required=True)
+    property_id = fields.Many2one('estate.property', string='Property')
+    property_type_id = fields.Many2one(comodel_name="estate.property.type", related="property_id.property_type_id", store=True)
+    
+    _sql_constraints = [
+            ('check_offer_price','CHECK(price > 0)','A property offer price must be strictly positive.')
+    ]
+
+    @api.depends('validity')
+    def _compute_deadline(self):
+        for record in self:
+            if record.create_date:
+                record.date_deadline = record.create_date + timedelta(record.validity)
+            else:
+                record.date_deadline = datetime.today() + timedelta(record.validity)
+
+    def _inverse_deadline(self):
+        for record in self:
+            if record.date_deadline and record.create_date:
+                record.validity = (record.date_deadline - record.create_date.date()).days
+            else:
+                record.validity = (record.date_deadline - datetime.today()).days
+
+    @api.depends('validity')
+    def _compute_sum(self):
+        for record in self:
+            record.sum = 7 + record.validity
+
+    @api.depends('sum')
+    def _compute_sum2(self):
+        for record in self:
+            record.sum2 = 7 + record.sum
+
+    def action_accept(self):
+        for record in self:
+            if record.property_id.state in ['sold', 'offer accepted']:
+                raise UserError("Already one offer is accepted.")
+            if record.status == 'accepted':
+                continue
+            record.status = 'accepted'
+            record.property_id.state = 'offer accepted'
+            record.property_id.buyer_id = self.partner_id
+            record.property_id.selling_price = self.price
+
+    def action_refuse(self):
+            if(self.status == 'accepted'):
+                self.status = 'refused'
+                self.property_id.buyer_id = False
+                self.property_id.selling_price = False
+            else: 
+                self.status = 'refused'
+    
+    @api.model
+    def create(self, offer):
+        property_id = self.env["estate.property"].browse(offer["property_id"])
+        if offer["price"] < max(property_id.offer_ids.mapped("price") + [0]):
+            raise UserError("Offer price must be higher than existing offer.")
+        property_id.state = "offer received"
+        return super().create(offer)
diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py
new file mode 100644
index 00000000000..5988f5c2fab
--- /dev/null
+++ b/estate/models/estate_property_tag.py
@@ -0,0 +1,16 @@
+from odoo import models, fields
+
+
+class estatePropertyTag(models.Model):
+    
+    _name = "estate.property.tag"
+    _description = "This is property Tag model"
+    _order = "name"
+
+    name = fields.Char(required=True, string="Tag")
+    active = fields.Boolean(required=True)
+    color = fields.Integer(default=12)
+
+    _sql_constraints = [
+            ('check_unique_tag_name','UNIQUE(name)','This tag is already exists.')
+    ]
diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py
new file mode 100644
index 00000000000..31b225bf68e
--- /dev/null
+++ b/estate/models/estate_property_type.py
@@ -0,0 +1,25 @@
+from odoo import models, fields, api
+
+
+class estatePropertyType(models.Model):
+    _name = "estate.property.type"
+    _description = "This is property Type table."
+    _order = "sequence, name desc"
+
+    name = fields.Char(required=True)
+    active = fields.Boolean(default=True)
+    number = fields.Integer(default=10)
+    sequence = fields.Integer('Sequence', default=5)
+    offer_count = fields.Integer(compute="_compute_offer_count")
+
+    property_ids = fields.One2many('estate.property', 'property_type_id', string='Property')
+    offer_ids = fields.One2many('estate.property.offer', 'property_type_id')
+    
+    _sql_constraints = [
+        ('check_unique_type_name', 'UNIQUE(name)', 'This type is already exists.')
+    ]
+    
+    @api.depends('offer_ids')
+    def _compute_offer_count(self):
+        for record in self:
+                record.offer_count = len(record.offer_ids)
diff --git a/estate/models/res_users.py b/estate/models/res_users.py
new file mode 100644
index 00000000000..933b9dcfb69
--- /dev/null
+++ b/estate/models/res_users.py
@@ -0,0 +1,7 @@
+from odoo import fields, models
+
+
+class resUser(models.Model):
+    _inherit = "res.users"
+
+    property_ids = fields.One2many(comodel_name="estate.property", inverse_name="seller_id", domain=[('state', 'in', ['new', 'offer received'])])
diff --git a/estate/reports/estate_property_detail_template.xml b/estate/reports/estate_property_detail_template.xml
new file mode 100644
index 00000000000..fb15c543367
--- /dev/null
+++ b/estate/reports/estate_property_detail_template.xml
@@ -0,0 +1,64 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <template id="estate_property_detail_template" name="Property Detail">
+        <title><t t-esc="property.name"/></title>
+        <t t-call="website.layout">
+            <style>
+                .property-container {
+                    max-width: 800px;
+                    margin: auto;
+                }
+                .property-card {
+                    border: 1px solid #ddd;
+                    border-radius: 8px;
+                    overflow: hidden;
+                    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+                }
+                .property-image {
+                    width: 100%;
+                    height: 300px;
+                    object-fit: cover;
+                    border-bottom: 1px solid #ddd;
+                }
+                .property-details {
+                    padding: 20px;
+                }
+                .property-details h5 {
+                    font-size: 1.5rem;
+                    font-weight: 600;
+                    margin-bottom: 15px;
+                    color: #333;
+                }
+                .property-details p {
+                    margin: 5px 0;
+                    font-size: 1rem;
+                    color: #555;
+                }
+                .property-details strong {
+                    color: #000;
+                }
+            </style>
+            <section class="container my-5 property-container">
+                <h2 class="text-center mb-4">
+                    <t t-esc="property.name"/> - Details
+                </h2>
+                <div class="property-card">
+                    <t t-if="property.property_image">
+                        <img t-attf-src="data:image/*;base64,#{property.property_image}" alt="Property Image" class="property-image"/>
+                    </t>
+                    <div class="property-details">
+                        <h5><t t-esc="property.name"/></h5>
+                        <p><strong>Salesman:</strong> <t t-esc="property.seller_id.name"/></p>
+                        <p><strong>State:</strong> <t t-esc="property.state"/></p>
+                        <p><strong>Expected Price:</strong> <t t-esc="property.expected_price"/> </p>
+                        <p><strong>Postcode:</strong> <t t-esc="property.postcode"/> </p>
+                        <p><strong>Date Availability:</strong> <t t-esc="property.data_availability"/> </p>
+                        <p><strong>Number of Bedrooms:</strong> <t t-esc="property.bedrooms"/> </p>
+                        <p><strong>Living Area:</strong> <t t-esc="property.garden_area"/> </p>
+                        <p><strong>Garden Area:</strong> <t t-esc="property.garden_area"/> </p>
+                    </div>
+                </div>
+            </section>
+        </t>
+    </template>
+</odoo>
diff --git a/estate/reports/estate_property_offer_report_template.xml b/estate/reports/estate_property_offer_report_template.xml
new file mode 100644
index 00000000000..ac0387c659b
--- /dev/null
+++ b/estate/reports/estate_property_offer_report_template.xml
@@ -0,0 +1,38 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <template id="estate_property_offer_report_template">
+        <t t-call="web.html_container">
+            <t t-foreach="docs" t-as="property">
+                <t t-call="web.external_layout">
+                    <div class="page">
+                        <h1>
+                            <b>
+                                Property Name:
+                            </b>
+                            <span t-field="property.name"/>
+                        </h1>
+                        <h6>
+                            <b>
+                                Salesman:
+                            </b>
+                            <span t-field="property.seller_id"/>
+                        </h6>
+                        <h6>
+                            <b>
+                                Expected Price:
+                            </b>
+                            <span t-field="property.expected_price"/>
+                        </h6>
+                        <h6>
+                            <b>
+                                State:
+                            </b>
+                            <span t-field="property.state"/>
+                        </h6>
+                        <t t-call="estate.print_offer_table"/>
+                    </div>
+                </t>
+            </t>
+        </t>
+    </template>
+</odoo>
diff --git a/estate/reports/estate_property_reports.xml b/estate/reports/estate_property_reports.xml
new file mode 100644
index 00000000000..cc759dfcf17
--- /dev/null
+++ b/estate/reports/estate_property_reports.xml
@@ -0,0 +1,23 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="estate_property_offer_report" model="ir.actions.report">
+        <field name="name">Property Offer Report</field>
+        <field name="model">estate.property</field>
+        <field name="report_type">qweb-pdf</field>
+        <field name="report_name">estate.estate_property_offer_report_template</field>
+        <field name="report_file">estate.estate_property_offer_report_template</field>
+        <field name="print_report_name">'%s Offers Report' % object.name</field>
+        <field name="binding_model_id" ref="model_estate_property"/>
+        <field name="binding_type">report</field>
+    </record>
+    <record id="estate_salesman_property_offer_report" model="ir.actions.report">
+        <field name="name">Property Offer Report</field>
+        <field name="model">res.users</field>
+        <field name="report_type">qweb-pdf</field>
+        <field name="report_name">estate.estate_salesman_property_offer_report_template</field>
+        <field name="report_file">estate.estate_salesman_property_offer_report_template</field>
+        <field name="print_report_name">'%s Properties Offer Report' % object.name</field>
+        <field name="binding_model_id" ref="model_res_users"/>
+        <field name="binding_type">report</field>
+    </record>
+</odoo>
diff --git a/estate/reports/estate_property_website_template.xml b/estate/reports/estate_property_website_template.xml
new file mode 100644
index 00000000000..7a8c9c978c8
--- /dev/null
+++ b/estate/reports/estate_property_website_template.xml
@@ -0,0 +1,60 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="menu_property" model="website.menu">
+        <field name="name">Properties</field>
+        <field name="url">/properties</field>
+        <field name="parent_id" ref="website.main_menu"/>
+    </record>
+
+    <template id="estate_property_website_template" name="Property">
+        <title>Properties</title>
+        <t t-call="website.layout">
+            <style>
+                .property-image {
+                    width: 100%; 
+                    height: 200px; 
+                    object-fit: cover; 
+                }
+            </style>
+            <section class="container my-5">
+                <h2 class="text-center mb-4">
+                    Available Properties
+                </h2>
+                <div class="row">
+                    <t t-foreach="properties" t-as="property">
+                        <div class="col-lg-4 col-md-6 col-sm-12 mb-4">
+                            <div class="card shadow border-light">
+                                <t t-if="property.property_image"> 
+                                    <img t-attf-src="data:image/*;base64,#{property.property_image}" alt="Property Image"/>
+                                </t>
+                                <div class="card-body">
+                                    <h5 class="card-title">
+                                        <t t-esc="property.name"/>
+                                    </h5>
+                                    <p class="card-text">
+                                        <strong>Salesman:</strong> 
+                                        <t t-esc="property.seller_id.name"/>
+                                    </p>
+                                    <p class="card-text">
+                                        <strong>State:</strong> 
+                                        <t t-esc="property.state"/>
+                                    </p>
+                                    <p class="card-text">
+                                        <strong>Expected Price:</strong>
+                                        <t t-esc="property.expected_price"/> $
+                                    </p>
+                                    <a t-att-href="'/property/' + str(property.id)" class="btn btn-primary">View Details</a>
+                                </div>
+                            </div>
+                        </div>
+                    </t>
+                </div>
+                <div class="pagination d-flex justify-content-between align-items-center">
+                    <a t-att-href="pager['page_previous']['url']" class="btn btn-secondary">Previous</a>
+                    <span>Page <t t-esc="pager['page']['num']"/> of <t t-esc="pager['page_count']"/></span>
+                    <a t-att-href="pager['page_next']['url']" class="btn btn-secondary">Next</a>
+                </div>
+            </section>
+        </t>
+    </template>
+</odoo>
diff --git a/estate/reports/estate_salesman_property_offer_report_template.xml b/estate/reports/estate_salesman_property_offer_report_template.xml
new file mode 100644
index 00000000000..3d05c2ed7a1
--- /dev/null
+++ b/estate/reports/estate_salesman_property_offer_report_template.xml
@@ -0,0 +1,45 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <template id="estate_salesman_property_offer_report_template">
+        <t t-call="web.html_container">
+            <t t-foreach="docs" t-as="res_user">
+                <t t-call="web.external_layout">
+                    <div class="page">
+                        <h1>
+                            <b>
+                                Salesman:
+                            </b>
+                            <span t-field="res_user.name"/>
+                        </h1>
+                        <t t-if="len(res_user.property_ids) > 0">
+                            <t t-foreach="res_user.property_ids" t-as="property">
+                                <h3>
+                                    <b>
+                                        Property Name:
+                                    </b>
+                                    <span t-field="property.name"/>
+                                </h3>
+                                <h6>
+                                    <b>
+                                        Expected Price:
+                                    </b>
+                                    <span t-field="property.expected_price"/>
+                                </h6>
+                                <h6>
+                                    <b>
+                                        State:
+                                    </b>
+                                    <span t-field="property.state"/>
+                                </h6>
+                                <t t-call="estate.print_offer_table"/>
+                            </t>
+                        </t>
+                        <t t-else="">
+                            <p>No property is under this user.</p>
+                        </t>
+                    </div>
+                </t>
+            </t>
+        </t>
+    </template>
+</odoo>
diff --git a/estate/reports/print_offer_table_subtemplate.xml b/estate/reports/print_offer_table_subtemplate.xml
new file mode 100644
index 00000000000..78cd5ad87e2
--- /dev/null
+++ b/estate/reports/print_offer_table_subtemplate.xml
@@ -0,0 +1,42 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <template id="print_offer_table">
+        <t t-if="len(property.offer_ids) > 0">
+            <table class="table mt16">
+                <thead>
+                    <tr>
+                        <th>Price</th>
+                        <th>Partner</th>
+                        <th>Validity (days)</th>
+                        <th>Deadline</th>
+                        <th>Status</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <tr t-foreach="property.offer_ids" t-as="offers">
+                        <td>
+                            <span t-field="offers.price"/>
+                        </td>
+                        <td>
+                            <span t-field="offers.partner_id"/>
+                        </td>
+                        <td>
+                            <span t-field="offers.validity"/>
+                        </td>
+                        <td>
+                            <span t-field="offers.date_deadline"/>
+                        </td>
+                        <td>
+                            <span t-field="offers.status"/>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+        </t>
+        <t t-else="">
+            <p>
+                No offer exists for property!!!
+            </p>
+        </t>
+    </template>
+</odoo>
diff --git a/estate/security/estate_security.xml b/estate/security/estate_security.xml
new file mode 100644
index 00000000000..836ae6958db
--- /dev/null
+++ b/estate/security/estate_security.xml
@@ -0,0 +1,34 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+
+    <record id="estate_group_user" model="res.groups">
+        <field name="name">Agent</field>
+        <field name="category_id" ref="base.module_category_real_estate_brokerage"></field>
+    </record>
+
+    <record id="estate_group_manager" model="res.groups">
+        <field name="name">Manager</field>
+        <field name="category_id" ref="base.module_category_real_estate_brokerage"></field>
+        <field name="implied_ids" eval="[(4, ref('estate.estate_group_user'))]"/>
+        <field name="users" eval="[(4, ref('base.user_admin'))]"/>
+    </record>
+
+    <record id="estate_property_record_rule_agent" model="ir.rule">
+        <field name="name">A description of the rule's for agent</field>
+        <field name="model_id" ref="estate.model_estate_property"/>
+        <field name="groups" eval="[Command.link(ref('estate.estate_group_user'))]"/>
+        <field name="domain_force">
+            ['|', ('seller_id', '=', user.id), ('seller_id', '=', False), ('company_id', 'in', company_ids)]
+        </field>
+    </record>
+
+    <record id="estate_property_record_rule_manager" model="ir.rule">
+        <field name="name">A description of the rule's for manager</field>
+        <field name="model_id" ref="estate.model_estate_property"/>
+        <field name="groups" eval="[Command.link(ref('estate.estate_group_manager'))]"/>
+        <field name="domain_force">
+            [(1, '=', 1)]
+        </field>
+    </record>
+
+</odoo>
diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv
new file mode 100644
index 00000000000..ef5f36a60b7
--- /dev/null
+++ b/estate/security/ir.model.access.csv
@@ -0,0 +1,13 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+
+access_estate_property,access_estate_property,model_estate_property,estate.estate_group_manager,1,1,1,0
+access_estate_property_type,access_estate_property_type,model_estate_property_type,estate.estate_group_manager,1,1,1,1
+access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,estate.estate_group_manager,1,1,1,1
+access_estate_property_offer,access_estate_property_offer,model_estate_property_offer,estate.estate_group_manager,1,1,1,1
+access_add_offer,access_add_offer,model_add_offer,estate.estate_group_manager,1,1,1,1
+
+access_estate_property,access_estate_property,model_estate_property,estate.estate_group_user,1,1,1,0
+access_estate_property_type,access_estate_property_type,model_estate_property_type,estate.estate_group_user,1,0,0,0
+access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,estate.estate_group_user,1,0,0,0
+access_estate_property_offer,access_estate_property_offer,model_estate_property_offer,estate.estate_group_user,1,1,1,1
+access_add_offer,access_add_offer,model_add_offer,estate.estate_group_user,1,1,1,1
diff --git a/estate/views/estate_menu.xml b/estate/views/estate_menu.xml
new file mode 100644
index 00000000000..fef0e406a7a
--- /dev/null
+++ b/estate/views/estate_menu.xml
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <menuitem id="estate_menu_root" name="Real State">
+        <menuitem id="estate_menu_root_first_advertisements" name="Advertisements" sequence="1">
+            <menuitem id="estate_menu_root_first_second_property" action="estate_property_action"/>
+        </menuitem>
+        <menuitem id="estate_menu_root_first_setting" name="Setting" sequence="2" groups="estate.estate_group_manager">
+            <menuitem id="estate_menu_root_first_second_type" action="estate_property_type_action" name="Property Type" sequence="1"/>
+            <menuitem id="estate_menu_root_first_second_tag" action="estate_property_tag_action" name="Property Tag" sequence="2"/>
+        </menuitem>
+    </menuitem> 
+</odoo>
diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml
new file mode 100644
index 00000000000..73089209f87
--- /dev/null
+++ b/estate/views/estate_property_offer_views.xml
@@ -0,0 +1,24 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="estate_property_offer_action" model="ir.actions.act_window">
+        <field name="name">Offers</field>
+        <field name="res_model">estate.property.offer</field>
+        <field name="view_mode">tree,form</field>
+        <field name="domain">[('property_type_id', '=', active_id)]</field>
+    </record>
+
+    <record id="estate_property_offer_view_tree" model="ir.ui.view">
+        <field name="name">estate_property_offer_view_tree</field>
+        <field name="model">estate.property.offer</field>
+        <field name="arch" type="xml">
+            <tree decoration-success="status == 'accepted'" decoration-danger="status == 'refused'">
+                <field name="property_id"/>
+                <field name="partner_id"/>
+                <field name="price"/>
+                <field name="validity"/>
+                <field name="date_deadline"/>
+                <field name="status"/>
+            </tree>
+        </field>
+    </record>
+</odoo>
diff --git a/estate/views/estate_property_tag_views.xml b/estate/views/estate_property_tag_views.xml
new file mode 100644
index 00000000000..5a2cd68dcf6
--- /dev/null
+++ b/estate/views/estate_property_tag_views.xml
@@ -0,0 +1,63 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="estate_property_tag_action" model="ir.actions.act_window">
+        <field name="name">Tag</field>
+        <field name="res_model">estate.property.tag</field>
+        <field name="view_mode">tree,form,kanban</field>
+    </record>
+    <record id="estate_property_tag_view_tree" model="ir.ui.view">
+        <field name="name">estate_property_tag_view_tree</field>
+        <field name="model">estate.property.tag</field>
+        <field name="arch" type="xml">
+            <tree>
+                <field name="name"/>
+                <field name="active"/>
+                <field name="color"/>
+            </tree>
+        </field>
+    </record>
+    <record id="estate_property_tag_view_form" model="ir.ui.view">
+        <field name="name">estate_property_tag_view_form</field>
+        <field name="model">estate.property.tag</field>
+        <field name="arch" type="xml">
+            <form>
+                <sheet>
+                    <h3>
+                        <field name="name"/>
+                    </h3>
+                    <group>
+                        <field name="active"/>
+                        <field name="color" help="Enter a number between 1 to 11 (inclusive)"/>
+                    </group>
+                </sheet>
+            </form>
+        </field>
+    </record>
+    <record id="estate_property_tag_view_search" model="ir.ui.view">
+        <field name="name">estate_property_tag_view_search</field>
+        <field name="model">estate.property.tag</field>
+        <field name="arch" type="xml">
+            <search string="Search Tag">
+                <field name="color" string="Color"/>
+            </search>
+        </field>
+    </record>
+    <record id="estate_property_tag_view_kanban" model="ir.ui.view">
+        <field name="name">estate_property_tag_view_kanban</field>
+        <field name="model">estate.property.tag</field>
+        <field name="arch" type="xml">
+            <kanban default_group_by="color">
+                <templates>
+                    <t t-name="kanban-box">
+                        <div class="oe_kanban_global_click">
+                            <h3>
+                                <field name="name"/>
+                            </h3>
+                            <field name="active"/>
+                        </div>
+                    </t>
+                </templates>
+            </kanban>
+        </field>
+    </record>
+</odoo>
diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml
new file mode 100644
index 00000000000..5133186d849
--- /dev/null
+++ b/estate/views/estate_property_type_views.xml
@@ -0,0 +1,57 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="estate_property_type_action" model="ir.actions.act_window">
+        <field name="name">Types</field>
+        <field name="res_model">estate.property.type</field>
+        <field name="view_mode">tree,form</field>
+    </record>
+
+    <record id="estate_property_type_view_tree" model="ir.ui.view">
+        <field name="name">estate_property_type_view_tree</field>
+        <field name="model">estate.property.type</field>
+        <field name="arch" type="xml">
+            <tree string="Property Type">
+                <field name="sequence" widget="handle"/>
+                <field name="name"/>
+                <field name="active" />
+                <field name="number"/>
+            </tree>
+        </field>
+    </record>
+
+    <record id="estate_property_type_view_form" model="ir.ui.view">
+        <field name="name">estate_property_type_view_form</field>
+        <field name="model">estate.property.type</field>
+        <field name="arch" type="xml">
+            <form>
+                <sheet>
+                    <div class="oe_button_box" name="button_box">
+                        <button name="%(estate_property_offer_action)d" type="action" class="oe_stat_button" icon="fa-money">
+                            <field name="offer_count" string="Offers" widget="statinfo"/>
+                        </button>
+                    </div>
+                    <h3>
+                        <field name="name"/>
+                    </h3>
+                    <group>
+                        <field name="active"/>
+                    </group>
+                    <notebook>
+                        <page string="Properties">
+                            <field name="property_ids">
+                                <tree create="False" decoration-success="state == 'offer received' or state == 'offer accepted'" decoration-bf="state == 'offer accepted'" decoration-muted="state == 'sold'">
+                                    <field name="name"/>
+                                    <field name="bedrooms"/>
+                                    <field name="expected_price"/>
+                                    <field name="best_offer"/>
+                                    <field name="selling_price"/>
+                                    <field name="state"/>
+                                </tree>
+                            </field>
+                        </page>
+                    </notebook>
+                </sheet>
+            </form>
+        </field>
+    </record>
+</odoo>
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml
new file mode 100644
index 00000000000..2c4b0fc5095
--- /dev/null
+++ b/estate/views/estate_property_views.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+   <record id="estate_property_action" model="ir.actions.act_window">
+        <field name="name">Properties</field>
+        <field name="res_model">estate.property</field>
+        <field name="view_mode">list,form,kanban</field>
+        <field name="context">{'search_default_state' : True}</field>
+    </record>
+
+     <record id="estate_property_view_tree" model="ir.ui.view">
+        <field name="name">estate_property_view_tree</field>
+        <field name="model">estate.property</field>
+        <field name="arch" type="xml">
+            <tree expand="1" default_order="expected_price desc, name desc" decoration-success="state == 'offer received' or state == 'offer accepted'" decoration-bf="state == 'offer accepted'" decoration-muted="state == 'sold'">
+               <header>
+                  <button string="Add Offer" name="%(estate.action_add_offer)d" type="action" class="oe_highlight"/>
+               </header>
+               <field name="name"/>
+               <field name="bedrooms"/>
+               <field name="expected_price" />
+               <field name="selling_price" />
+               <field name="best_offer" />
+               <field name="state"/>
+            </tree>
+        </field>
+     </record>
+
+     <record id="estate_property_view_form" model="ir.ui.view">
+         <field name="name">estate_property_view_form</field>
+         <field name="model">estate.property</field>
+         <field name="arch" type="xml">
+            <form string="My New House">
+               <header>
+                  <button string="Sold" name="action_sold" type="object" class="oe_highlight" invisible="state == 'sold' or state == 'cancelled'" />
+                  <button string="Cancel" name="action_cancelled" type="object" invisible="state == 'sold' or state == 'cancelled'" />
+                  <field name="state" widget="statusbar" />
+               </header>
+               <sheet>
+                  <field name="property_image" widget="image" class="oe_avatar"/>
+                  <h2>
+                     Name:
+                     <field name="name"/>
+                  </h2>
+                  <group>
+                     <group>
+                        <field name="property_type_id" options="{'no_create': true}" />
+                        <field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}" />
+                        <field name="postcode"/>
+                     </group>
+                     <group>
+                        <field name="expected_price"/>
+                        <field name="best_offer" />
+                        <field name="selling_price" />
+                        <field name="company_id" />
+                     </group>
+                  </group>
+                  <notebook>
+                     <page string="Description">
+                        <group>
+                           <group>
+                              <field name="description"/>
+                              <field name="data_availability"/>
+                              <field name="bedrooms" string="Number of bedrooms"/>
+                              <field name="living_area"/>
+                              <field name="garage"/>
+                              <field name="garden"/>
+                              <field name="garden_area" invisible="not garden"/>
+                              <field name="garden_orientation" invisible="not garden"/>
+                              <field name="totalArea"/>
+                           </group>
+                        </group>
+                  </page>
+                  <page string="Sales Information">
+                     <group>
+                        <field name="seller_id"/>
+                        <field name="buyer_id"/>
+                     </group>
+                  </page>
+                  <page string="Offer">
+                        <field name="offer_ids" readonly="state == 'offer accepted' or state == 'sold' or state == 'cancelled'" >
+                           <tree editable="bottom" decoration-success="status == 'accepted'" decoration-danger="status == 'refused'" >
+                              <field name="partner_id"/>
+                              <field name="price"/>
+                              <field name="validity" />
+                              <field name="date_deadline"  />
+                              <button name="action_accept" type="object" icon="fa-check" invisible="status == 'accepted' or status == 'refused'" />
+                              <button name="action_refuse" type="object" icon="fa-times" invisible="status == 'accepted' or status == 'refused'" />
+                              <field name="status" />
+                           </tree>
+                        </field>
+                  </page>
+               </notebook>
+            </sheet>
+            </form>
+         </field>
+     </record>
+
+     <record id="estate_property_view_kanban" model="ir.ui.view">
+         <field name="name">estate.property.view.kanban</field>
+         <field name="model">estate.property</field>
+         <field name="arch" type="xml">
+            <kanban default_group_by="property_type_id" records_draggable="False">
+               <field name="state"/>
+               <templates>
+                  <t t-name="kanban-box">
+                     <div class="oe_kanban_global_click">
+                        <h3>
+                           <field name="name"/>
+                        </h3>
+                        <div>
+                           Expected Price:
+                           <field name="expected_price"/>
+                        </div>
+                        <div t-if="record.state.raw_value == 'offer received'" >
+                           Best Offer Price:
+                           <field name="best_offer"/>
+                        </div>
+                        <div t-if="record.state.raw_value == 'offer accepted'" >
+                           Selling price:
+                           <field name="selling_price"/>
+                        </div>
+                        <div style="margin-top: 10px;"></div>
+                        <field name="tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
+                     </div>
+                  </t>
+               </templates>
+            </kanban>
+         </field>
+     </record>
+     
+     <record id="estate_property_view_search" model="ir.ui.view">
+         <field name="name">estate_property_view_search</field>
+         <field name="model">estate.property</field>
+         <field name="arch" type="xml">
+            <search>
+               <field name="name" string="Name" />
+               <field name="selling_price" />
+               <field name="expected_price" string="Expected Price" />
+               <field string="Living Area" name="living_area" filter_domain="[('living_area', '>=', self)]" />
+               <filter string="Available" name="state" domain="['|', ('state', '=', 'new'),('state', '=', 'sold')]" />
+               <group string="Group By">
+                  <filter string="Postcode" name="postcode" context="{'group_by':'postcode'}"/>
+                  <filter string="Bedroom" name="bedrooms" context="{'group_by':'bedrooms'}"/> 
+               </group>
+            </search>
+         </field>
+     </record>
+</odoo> 
diff --git a/estate/views/res_users_views.xml b/estate/views/res_users_views.xml
new file mode 100644
index 00000000000..f67d9f1dac1
--- /dev/null
+++ b/estate/views/res_users_views.xml
@@ -0,0 +1,15 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="res_user_views_form" model="ir.ui.view">
+        <field name="name">res_user_views_form</field>
+        <field name="model">res.users</field>
+        <field name="inherit_id" ref="base.view_users_form"/>
+        <field name="arch" type="xml">
+            <page name="preferences" position="after">
+                <page name="estate" string="Real Estate Properties" readonly="true" >
+                    <field name="property_ids"/>
+                </page>
+            </page>
+        </field>
+    </record>
+</odoo>
diff --git a/estate/wizards/__init__.py b/estate/wizards/__init__.py
new file mode 100644
index 00000000000..7e004753b11
--- /dev/null
+++ b/estate/wizards/__init__.py
@@ -0,0 +1 @@
+from . import add_offer
diff --git a/estate/wizards/add_offer.py b/estate/wizards/add_offer.py
new file mode 100644
index 00000000000..565aa65b18e
--- /dev/null
+++ b/estate/wizards/add_offer.py
@@ -0,0 +1,21 @@
+from odoo import models, fields
+
+
+class addOffer(models.TransientModel):
+
+    _name = "add.offer"
+    _description = "You can add a offer directly in multiple properties."
+
+    price = fields.Float(required=True)
+    partner_id = fields.Many2one('res.partner', string='Buyer', required=True)
+
+    def action_make_an_offer(self):
+        select_property_id = self.env.context['active_ids']
+        properties = self.env["estate.property"].browse(select_property_id)
+
+        for property in properties:
+            self.env["estate.property.offer"].create({
+                'price': self.price,
+                'partner_id': self.partner_id.id,
+                'property_id': property.id
+            })
diff --git a/estate/wizards/add_offer.xml b/estate/wizards/add_offer.xml
new file mode 100644
index 00000000000..e515189f75c
--- /dev/null
+++ b/estate/wizards/add_offer.xml
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="action_add_offer" model="ir.actions.act_window">
+        <field name="name">Add Offer</field>
+        <field name="res_model">add.offer</field>
+        <field name="view_mode">form</field>
+        <field name="target">new</field>
+    </record>
+
+    <record id="add_offer_view_form" model="ir.ui.view">
+        <field name="name">add.offer.view.form</field>
+        <field name="model">add.offer</field>
+        <field name="arch" type="xml">
+            <form string="Add Offer">
+                <group>
+                    <field name="price"/>
+                    <field name="partner_id"/>
+                </group>
+                <footer>
+                    <button string="Make an Offer" name="action_make_an_offer" type="object" class="oe_highlight"/>
+                    <button string="Cancel" class="btn-secondary" special="cancel"/>
+                </footer>
+            </form>
+        </field>
+    </record>
+</odoo>
diff --git a/estate_account/__init__.py b/estate_account/__init__.py
new file mode 100644
index 00000000000..0650744f6bc
--- /dev/null
+++ b/estate_account/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/estate_account/__manifest__.py b/estate_account/__manifest__.py
new file mode 100644
index 00000000000..51c64289705
--- /dev/null
+++ b/estate_account/__manifest__.py
@@ -0,0 +1,14 @@
+{
+    'name': "Estate Account",
+    'depends': ['estate', 'account'],
+    'author': "Sahil Mangukiya",
+    'description': "This is a estate account module.",
+    'data': [
+        'reports/estate_property_offer_report_inherit_template.xml',
+        'reports/estate_salesman_property_offer_report_inherit_template.xml',
+    ],
+    'demo': [
+    ],
+    'installable': True,
+    'application': False,
+}
diff --git a/estate_account/models/__init__.py b/estate_account/models/__init__.py
new file mode 100644
index 00000000000..5e1963c9d2f
--- /dev/null
+++ b/estate_account/models/__init__.py
@@ -0,0 +1 @@
+from . import estate_property
diff --git a/estate_account/models/estate_property.py b/estate_account/models/estate_property.py
new file mode 100644
index 00000000000..86146043e32
--- /dev/null
+++ b/estate_account/models/estate_property.py
@@ -0,0 +1,37 @@
+from odoo import models, Command, fields
+
+
+class estateProperty(models.Model):
+
+    _inherit = 'estate.property'
+
+    def action_sold(self):
+        supper_call = super().action_sold()
+
+        invoice_price = {
+            "name": self.name,
+            "quantity": 1,
+            "price_unit": self.selling_price * 1.06
+        }
+
+        invoice_administrative_fees = {
+            "name": "Administrative Fees",
+            "quantity": 1,
+            "price_unit": 100.00
+        }
+
+        # print(" reached ".center(100, '='))
+        # print(self.env["account.move"].check_access_rights('write'))
+        # print(self.env["account.move"].check_access_rule('write'))
+
+        self.env["account.move"].sudo().create({
+            "name": self.name + " Invoice",
+            "partner_id": self.buyer_id.id,
+            "move_type": "out_invoice",
+            "invoice_line_ids": [
+                Command.create(invoice_price),
+                Command.create(invoice_administrative_fees)
+            ]
+        })
+
+        return supper_call
diff --git a/estate_account/reports/estate_property_offer_report_inherit_template.xml b/estate_account/reports/estate_property_offer_report_inherit_template.xml
new file mode 100644
index 00000000000..fc9c671d14a
--- /dev/null
+++ b/estate_account/reports/estate_property_offer_report_inherit_template.xml
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <template id="estate_property_offer_report_inherit_template" inherit_id="estate.estate_property_offer_report_template">
+        <xpath expr="//div//h6[3]" position="after">
+            <t t-if="property.state == 'sold'">
+                <p>
+                    <b>
+                        !!! Invoice has already been created !!!
+                    </b>
+                </p>
+            </t>
+        </xpath>
+    </template>
+</odoo>
diff --git a/estate_account/reports/estate_salesman_property_offer_report_inherit_template.xml b/estate_account/reports/estate_salesman_property_offer_report_inherit_template.xml
new file mode 100644
index 00000000000..214d0750204
--- /dev/null
+++ b/estate_account/reports/estate_salesman_property_offer_report_inherit_template.xml
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <template id="estate_salesman_property_offer_report_inherit_template" inherit_id="estate.estate_salesman_property_offer_report_template">
+        <xpath expr="//div//h6[2]" position="after">
+            <t t-if="property.state == 'offer received'">
+                <p>
+                    <b>
+                        !!! Offers are received for this Property. !!!
+                    </b>
+                </p>
+            </t>
+        </xpath>
+    </template>
+</odoo>
diff --git a/stock_install/__init__.py b/stock_install/__init__.py
new file mode 100644
index 00000000000..9a7e03eded3
--- /dev/null
+++ b/stock_install/__init__.py
@@ -0,0 +1 @@
+from . import models
\ No newline at end of file
diff --git a/stock_install/__manifest__.py b/stock_install/__manifest__.py
new file mode 100644
index 00000000000..0a5f03cf466
--- /dev/null
+++ b/stock_install/__manifest__.py
@@ -0,0 +1,15 @@
+{
+    'name': "stock_install",
+    'depends': ['stock'],
+    'author': "sahm@odoo.com",
+    'description': "This is my stock_install module.",
+    'data': [
+        'views/res_config_settings_views.xml'
+    ],
+    'demo': [
+
+    ],
+    'installable': True,
+    'application': False,
+    'auto_install': True
+}
diff --git a/stock_install/models/__init__.py b/stock_install/models/__init__.py
new file mode 100644
index 00000000000..e1abf59ce87
--- /dev/null
+++ b/stock_install/models/__init__.py
@@ -0,0 +1 @@
+from . import res_config_setting
\ No newline at end of file
diff --git a/stock_install/models/res_config_setting.py b/stock_install/models/res_config_setting.py
new file mode 100644
index 00000000000..014bef2a711
--- /dev/null
+++ b/stock_install/models/res_config_setting.py
@@ -0,0 +1,7 @@
+from odoo import fields, models
+
+
+class ResConfigSettings(models.TransientModel):
+    _inherit = 'res.config.settings'
+
+    module_stock_transport = fields.Boolean("Dispatch Management System")
\ No newline at end of file
diff --git a/stock_install/views/res_config_settings_views.xml b/stock_install/views/res_config_settings_views.xml
new file mode 100644
index 00000000000..5ef00cea9f1
--- /dev/null
+++ b/stock_install/views/res_config_settings_views.xml
@@ -0,0 +1,15 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="res_config_setting_inherit_res_config_setting" model="ir.ui.view">
+        <field name="name">res_config_setting_inherit_res_config_setting</field>
+        <field name="model">res.config.settings</field>
+        <field name="inherit_id" ref="stock.res_config_settings_view_form"/>
+        <field name="arch" type="xml">
+            <xpath expr="//setting[@id='delivery']" position="after">
+                <setting id="dispatch_management_system" help="Transport Management: organize pack in your fleet, or carriers.">
+                    <field name="module_stock_transport"></field>
+                </setting>
+            </xpath>
+        </field>
+    </record>
+</odoo>
\ No newline at end of file
diff --git a/stock_transport/__init__.py b/stock_transport/__init__.py
new file mode 100644
index 00000000000..0650744f6bc
--- /dev/null
+++ b/stock_transport/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/stock_transport/__manifest__.py b/stock_transport/__manifest__.py
new file mode 100644
index 00000000000..aa65ce2821f
--- /dev/null
+++ b/stock_transport/__manifest__.py
@@ -0,0 +1,19 @@
+{
+    'name': "stock_transport",
+    'depends': ['stock_picking_batch', 'fleet'],
+    'author': "sahm@odoo.com",
+    'description': "This is my stock_transport module.",
+    'data': [
+        'security/stock_transport_security.xml',
+        'security/ir.model.access.csv',
+        'views/stock_picking_batch_views.xml',
+        'views/fleet_vehicle_model_views.xml',
+        'views/stock_picking_views.xml',
+    ],
+    'demo': [
+
+    ],
+    'installable': True,
+    'application': False,
+    'auto_install': False
+}
diff --git a/stock_transport/models/__init__.py b/stock_transport/models/__init__.py
new file mode 100644
index 00000000000..0d3615884af
--- /dev/null
+++ b/stock_transport/models/__init__.py
@@ -0,0 +1,4 @@
+from . import fleet_vehicle_model_category
+from . import dock
+from . import stock_picking_batch
+from . import stock_picking
diff --git a/stock_transport/models/dock.py b/stock_transport/models/dock.py
new file mode 100644
index 00000000000..06c4cad47b3
--- /dev/null
+++ b/stock_transport/models/dock.py
@@ -0,0 +1,7 @@
+from odoo import fields, models
+
+
+class dock(models.Model):
+    _name = 'dock'
+
+    name = fields.Char()
diff --git a/stock_transport/models/fleet_vehicle_model_category.py b/stock_transport/models/fleet_vehicle_model_category.py
new file mode 100644
index 00000000000..09df774a749
--- /dev/null
+++ b/stock_transport/models/fleet_vehicle_model_category.py
@@ -0,0 +1,12 @@
+from odoo import fields, models
+
+
+class FleetVehicleModelCategory(models.Model):
+    _inherit = 'fleet.vehicle.model.category'
+
+    max_weight = fields.Float()
+    max_volume = fields.Float()
+
+    def _compute_display_name(self):
+        for record in self:
+            record.display_name = record.name + ' (' + str(record.max_weight) + ' kg, ' + str(record.max_volume) + ' m3)'
diff --git a/stock_transport/models/stock_picking.py b/stock_transport/models/stock_picking.py
new file mode 100644
index 00000000000..3244053dc08
--- /dev/null
+++ b/stock_transport/models/stock_picking.py
@@ -0,0 +1,15 @@
+from odoo import fields, models, api
+
+
+class Picking(models.Model):
+    _inherit = 'stock.picking'
+
+    volume = fields.Float(compute="_compute_volume")
+
+    @api.depends('move_ids.product_id.volume')
+    def _compute_volume(self):
+        for record in self:
+            total_volume = 0
+            for move_line in record.move_ids:
+                total_volume = total_volume + move_line.quantity * move_line.product_id.volume
+            record.volume = total_volume
diff --git a/stock_transport/models/stock_picking_batch.py b/stock_transport/models/stock_picking_batch.py
new file mode 100644
index 00000000000..aae62bd2e8f
--- /dev/null
+++ b/stock_transport/models/stock_picking_batch.py
@@ -0,0 +1,80 @@
+from odoo import fields, models, api
+
+
+class stockPickingBatch(models.Model):
+    _inherit = 'stock.picking.batch'
+    _rec_name = 'name'
+
+    weight_percentage = fields.Float(compute="_compute_weight_percentage", string='Weight')
+    volume_percentage = fields.Float(compute="_compute_volume_percentage", string='Volume')
+
+    weight = fields.Float(string="Weight", compute="_compute_weight", store=True)
+    volume = fields.Float(string="Volume", compute="_compute_volume", store=True)
+    number_of_transfer = fields.Integer(string="Transfer", compute="_compute_number_of_transfer", store=True)
+    number_of_line = fields.Integer(string="Line", compute="_compute_number_of_line", store=True)
+
+    dock_id = fields.Many2one(comodel_name='dock', string="Dock")
+    vehicle_id = fields.Many2one(comodel_name='fleet.vehicle', string="Vehicle")
+    category_id = fields.Many2one(comodel_name='fleet.vehicle.model.category', string='Category', compute='_compute_category', store=True)
+
+    @api.depends('vehicle_id', 'vehicle_id.category_id')
+    def _compute_category(self):
+        for record in self:
+            record.category_id = record.vehicle_id.category_id.id
+
+    @api.depends('picking_ids', 'picking_ids.move_ids', 'category_id.max_weight', 'picking_ids.move_ids.product_id.weight')
+    def _compute_weight_percentage(self):
+        for record in self:
+            max_weight = record.category_id.max_weight
+            total_weight = 0
+            for picking_line in record.picking_ids:
+                for move_line in picking_line.move_ids:
+                    total_weight = total_weight + move_line.product_id.weight * move_line.quantity
+            if max_weight == 0:
+                record.weight_percentage = 0.0
+            else:
+                record.weight_percentage = total_weight / max_weight * 100
+
+    @api.depends('picking_ids', 'picking_ids.move_ids', 'category_id.max_volume', 'picking_ids.move_ids.product_id.volume')
+    def _compute_volume_percentage(self):
+        for record in self:
+            max_volume = record.category_id.max_volume
+            total_volume = 0
+            for picking_line in record.picking_ids:
+                for move_line in picking_line.move_ids:
+                    total_volume = total_volume + move_line.product_id.volume * move_line.quantity
+            if max_volume == 0:
+                record.volume_percentage = 0.0
+            else:
+                record.volume_percentage = total_volume / max_volume * 100
+    
+    @api.depends('picking_ids', 'picking_ids.move_ids', 'picking_ids.move_ids.product_id.weight')
+    def _compute_weight(self):
+        for record in self:
+            total_weight = 0
+            for picking_line in record.picking_ids:
+                for move_line in picking_line.move_ids:
+                    total_weight = total_weight + move_line.product_id.weight * move_line.quantity
+            record.weight = total_weight
+
+    @api.depends('picking_ids', 'picking_ids.move_ids', 'picking_ids.move_ids.product_id.volume')
+    def _compute_volume(self):
+        for record in self:
+            total_volume = 0
+            for picking_line in record.picking_ids:
+                for move_line in picking_line.move_ids:
+                    total_volume = total_volume + move_line.product_id.volume * move_line.quantity
+            record.volume = total_volume
+
+    @api.depends('picking_ids')
+    def _compute_number_of_transfer(self):
+        for record in self:
+            record.number_of_transfer = len(record.picking_ids)
+    
+    @api.depends('picking_ids', 'picking_ids.move_ids')
+    def _compute_number_of_line(self):
+        for record in self:
+            total_lines = 0
+            for picking_line in record.picking_ids:
+                    total_lines = total_lines + len(picking_line.move_ids)
+            record.number_of_line = total_lines
diff --git a/stock_transport/security/ir.model.access.csv b/stock_transport/security/ir.model.access.csv
new file mode 100644
index 00000000000..db73dffc716
--- /dev/null
+++ b/stock_transport/security/ir.model.access.csv
@@ -0,0 +1,3 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+
+access_dock,access_dock,model_dock,stock_transport.group_stock_transport_admin,1,1,1,1
diff --git a/stock_transport/security/stock_transport_security.xml b/stock_transport/security/stock_transport_security.xml
new file mode 100644
index 00000000000..5e1bd10f696
--- /dev/null
+++ b/stock_transport/security/stock_transport_security.xml
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="group_stock_transport_admin" model="res.groups">
+        <field name="name">Admin</field>
+        <field name="users" eval="[(4, ref('base.user_admin'))]"/>
+    </record>
+</odoo>
\ No newline at end of file
diff --git a/stock_transport/views/fleet_vehicle_model_views.xml b/stock_transport/views/fleet_vehicle_model_views.xml
new file mode 100644
index 00000000000..ba2c186891a
--- /dev/null
+++ b/stock_transport/views/fleet_vehicle_model_views.xml
@@ -0,0 +1,28 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="fleet_vehicle_model_category_view_tree_inherit_stock_transport" model="ir.ui.view">
+        <field name="name">fleet.vehicle.model.category.view.tree.inherit</field>
+        <field name="model">fleet.vehicle.model.category</field>
+        <field name="inherit_id" ref="fleet.fleet_vehicle_model_category_view_tree"/>
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='name']" position="after">
+                <field name="max_weight" groups="stock_transport.group_stock_transport_admin"></field>
+                <field name="max_volume" groups="stock_transport.group_stock_transport_admin"></field>
+            </xpath>
+        </field>
+    </record>
+
+    <record id="fleet_vehicle_model_category_view_form_inherit_stock_transport" model="ir.ui.view">
+        <field name="name">fleet.vehicle.model.category.view.form.inherit</field>
+        <field name="model">fleet.vehicle.model.category</field>
+        <field name="inherit_id" ref="fleet.fleet_vehicle_model_category_view_form"/>
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='name']" position="after">
+                <field name="max_weight" groups="stock_transport.group_stock_transport_admin"></field>
+            </xpath>
+            <xpath expr="//field[@name='sequence']" position="after">
+                <field name="max_volume" groups="stock_transport.group_stock_transport_admin"></field>
+            </xpath>
+        </field>
+    </record>
+</odoo>
diff --git a/stock_transport/views/stock_picking_batch_views.xml b/stock_transport/views/stock_picking_batch_views.xml
new file mode 100644
index 00000000000..7a4cec9cd30
--- /dev/null
+++ b/stock_transport/views/stock_picking_batch_views.xml
@@ -0,0 +1,51 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="stock_picking_batch_form_inherit_stock_transport" model="ir.ui.view">
+        <field name="name">stock.picking.batch.form.inherit</field>
+        <field name="model">stock.picking.batch</field>
+        <field name="inherit_id" ref="stock_picking_batch.stock_picking_batch_form"/>
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='scheduled_date']" position="after">
+                <field name="dock_id" groups="stock_transport.group_stock_transport_admin"/>
+                <field name="vehicle_id" placeholder="Third party provider" groups="stock_transport.group_stock_transport_admin"/>
+                <field name="category_id" invisible="not vehicle_id" groups="stock_transport.group_stock_transport_admin"/>
+                <field name="weight_percentage" widget="progressbar" invisible="not category_id" groups="stock_transport.group_stock_transport_admin"/>
+                <field name="volume_percentage" widget="progressbar" invisible="not category_id" groups="stock_transport.group_stock_transport_admin"/>
+            </xpath>
+            <xpath expr="//button[@name='action_open_label_layout']" position="attributes">
+                <attribute name="groups">stock_transport.group_stock_transport_admin</attribute>
+            </xpath>
+        </field>
+    </record>
+
+    <record id="stock_picking_batch.stock_picking_batch_action" model="ir.actions.act_window">
+        <field name="view_mode">tree,kanban,graph,gantt,form</field>
+    </record>
+
+    <record id="stock_picking_batch_view_graph" model="ir.ui.view">
+        <field name="name">stock.picking.batch.view.graph</field>
+        <field name="model">stock.picking.batch</field>
+        <field name="arch" type="xml">
+            <graph string="Batch Transfer Graph View" type="bar">
+                <field name="scheduled_date" interval="day"></field>
+                <field name="category_id"></field>
+                <field name="number_of_transfer" type="measure"></field>
+            </graph>
+        </field>
+    </record>
+
+    <record id="stock_picking_batch_view_gantt" model="ir.ui.view">
+        <field name="name">stock.picking.batch.view.gantt</field>
+        <field name="model">stock.picking.batch</field>
+        <field name="arch" type="xml">
+            <gantt color="id" string="Gantt View" date_start="scheduled_date" date_stop="scheduled_date" 
+            default_group_by="dock_id,vehicle_id" 
+            default_scale="week"
+            decoration-info="state == 'draft'"
+            >
+                <field name="state"></field>
+            </gantt>
+        </field>
+    </record>
+
+</odoo>
diff --git a/stock_transport/views/stock_picking_views.xml b/stock_transport/views/stock_picking_views.xml
new file mode 100644
index 00000000000..dabb9596806
--- /dev/null
+++ b/stock_transport/views/stock_picking_views.xml
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="vpicktree_inherit_stock_transport" model="ir.ui.view">
+        <field name="name">vpicktree.inherit</field>
+        <field name="model">stock.picking</field>
+        <field name="inherit_id" ref="stock.vpicktree"/>
+        <field name="mode">extension</field>
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='scheduled_date']" position="after">
+                <field name="volume" groups="stock_transport.group_stock_transport_admin"/>
+            </xpath>
+        </field>
+    </record>
+</odoo>
\ No newline at end of file
diff --git a/sub_product/__init__.py b/sub_product/__init__.py
new file mode 100644
index 00000000000..50235cbb122
--- /dev/null
+++ b/sub_product/__init__.py
@@ -0,0 +1,3 @@
+from . import models
+from . import wizard
+from . import report
diff --git a/sub_product/__manifest__.py b/sub_product/__manifest__.py
new file mode 100644
index 00000000000..25bcf62f638
--- /dev/null
+++ b/sub_product/__manifest__.py
@@ -0,0 +1,19 @@
+{
+    'name': "sub_product",
+    'depends': ['sale_management'],
+    'author': "sahm@odoo.com",
+    'description': "This module will help to add sub-product in product.",
+    'data': [
+        'security/ir.model.access.csv',
+        'report/ir_actions_report_templates.xml',
+        'wizard/sub_products_views.xml',
+        'views/product_views.xml',
+        'views/sale_order_views.xml',
+    ],
+    'demo': [
+
+    ],
+    'installable': True,
+    'application': False,
+    'auto_install': False
+}
diff --git a/sub_product/models/__init__.py b/sub_product/models/__init__.py
new file mode 100644
index 00000000000..8f2f8c0cbc1
--- /dev/null
+++ b/sub_product/models/__init__.py
@@ -0,0 +1,3 @@
+from . import product_template
+from . import sale_order_line
+from . import sale_order
diff --git a/sub_product/models/product_template.py b/sub_product/models/product_template.py
new file mode 100644
index 00000000000..61689af56fb
--- /dev/null
+++ b/sub_product/models/product_template.py
@@ -0,0 +1,9 @@
+from odoo import fields, models
+
+
+class ProductTemplate(models.Model):
+    _inherit = 'product.template'
+
+    is_kit = fields.Boolean()
+    sub_product_ids = fields.Many2many('product.product')
+
diff --git a/sub_product/models/sale_order.py b/sub_product/models/sale_order.py
new file mode 100644
index 00000000000..9131218859c
--- /dev/null
+++ b/sub_product/models/sale_order.py
@@ -0,0 +1,8 @@
+from odoo import fields, models
+
+
+class SaleOrder(models.Model):
+    _inherit = 'sale.order'
+
+    print_in_report = fields.Boolean()
+    
\ No newline at end of file
diff --git a/sub_product/models/sale_order_line.py b/sub_product/models/sale_order_line.py
new file mode 100644
index 00000000000..94caaf465d6
--- /dev/null
+++ b/sub_product/models/sale_order_line.py
@@ -0,0 +1,9 @@
+from odoo import fields, models, api
+
+
+class SaleOrderLine(models.Model):
+    _inherit = 'sale.order.line'
+
+    is_kit = fields.Boolean(related='product_template_id.is_kit')
+    sale_order_line_id = fields.Many2one('sale.order.line', ondelete='cascade')
+    previously_set_price = fields.Float()
diff --git a/sub_product/report/ir_actions_report_templates.xml b/sub_product/report/ir_actions_report_templates.xml
new file mode 100644
index 00000000000..14de2733de6
--- /dev/null
+++ b/sub_product/report/ir_actions_report_templates.xml
@@ -0,0 +1,18 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <template id="report_saleorder_document_inherit_sub_product" name="Report" inherit_id="sale.report_saleorder_document">
+        <xpath expr="//tbody//tr" position="attributes">
+            <attribute name="t-if">(line.order_id.print_in_report) or (not line.sale_order_line_id)</attribute>
+        </xpath>
+    </template>
+    <template id="sale_order_portal_content_inherit_sub_product" name="Portal Preview" inherit_id="sale.sale_order_portal_content">
+        <xpath expr="//tbody[@class='sale_tbody']//tr" position="attributes">
+            <attribute name="t-if">(line.order_id.print_in_report) or (not line.sale_order_line_id)</attribute>
+        </xpath>
+    </template>
+    <template id="report_invoice_document_inherit_sub_product" name="Invoice" inherit_id="account.report_invoice_document">
+        <xpath expr="//tbody[@class='invoice_tbody']//tr" position="attributes">
+            <attribute name="t-if">(line.sale_line_ids.order_id.print_in_report) or (not line.sale_line_ids.sale_order_line_id)</attribute>
+        </xpath>
+    </template>
+</odoo>
\ No newline at end of file
diff --git a/sub_product/security/ir.model.access.csv b/sub_product/security/ir.model.access.csv
new file mode 100644
index 00000000000..f037aeecff4
--- /dev/null
+++ b/sub_product/security/ir.model.access.csv
@@ -0,0 +1,4 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+
+access_sub_products,access_sub_products,model_sub_products,base.group_user,1,1,1,1
+access_sub_products_line,access_sub_products_line,model_sub_products_line,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/sub_product/views/product_views.xml b/sub_product/views/product_views.xml
new file mode 100644
index 00000000000..65824847f9d
--- /dev/null
+++ b/sub_product/views/product_views.xml
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="product_template_form_view_inherit_sub_product" model="ir.ui.view">
+        <field name="name">product.template.view.form.inherit</field>
+        <field name="model">product.template</field>
+        <field name="inherit_id" ref="product.product_template_form_view"/>
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='product_tooltip']" position="after">
+                <field name="is_kit"/>
+                <field name="sub_product_ids" widget="many2many_tags" invisible="not is_kit"/>
+            </xpath>
+        </field>
+    </record>
+</odoo>
\ No newline at end of file
diff --git a/sub_product/views/sale_order_views.xml b/sub_product/views/sale_order_views.xml
new file mode 100644
index 00000000000..f971259c7d6
--- /dev/null
+++ b/sub_product/views/sale_order_views.xml
@@ -0,0 +1,45 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="view_order_form_inherit_sub_product" model="ir.ui.view">
+        <field name="name">sale.order.view.form.inherit</field>
+        <field name="model">sale.order</field>
+        <field name="inherit_id" ref="sale.view_order_form"/>
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='payment_term_id']" position="after">
+                <field name="print_in_report"/>
+            </xpath>
+            <xpath expr="//field[@name='product_template_id']" position="after">
+                <field name="is_kit" optional='hide'/>
+                <field name="sale_order_line_id" optional='hide' readonly="sale_order_line_id"/>
+                <button string="Sub Product" name="sub_product.action_sub_products" type="action" class="oe_highlight" invisible="state == 'sale' or not is_kit" context="{'product_name': name}" />
+            </xpath>
+            <xpath expr="//tree//field[@name='product_id']" position="attributes">
+                <attribute name="readonly">sale_order_line_id</attribute>
+            </xpath>
+            <xpath expr="//tree//field[@name='product_template_id']" position="attributes">
+                <attribute name="readonly">sale_order_line_id</attribute>
+            </xpath>
+            <xpath expr="//tree//field[@name='name']" position="attributes">
+                <attribute name="readonly">sale_order_line_id</attribute>
+            </xpath>
+            <xpath expr="//tree//field[@name='product_uom_qty']" position="attributes">
+                <attribute name="readonly">sale_order_line_id</attribute>
+            </xpath>
+            <xpath expr="//tree//field[@name='customer_lead']" position="attributes">
+                <attribute name="readonly">sale_order_line_id</attribute>
+            </xpath>
+            <xpath expr="//tree//field[@name='price_unit']" position="attributes">
+                <attribute name="readonly">sale_order_line_id</attribute>
+            </xpath>
+            <xpath expr="//tree//field[@name='tax_id']" position="attributes">
+                <attribute name="readonly">sale_order_line_id</attribute>
+            </xpath>
+            <xpath expr="//tree//field[@name='price_subtotal']" position="attributes">
+                <attribute name="readonly">sale_order_line_id</attribute>
+            </xpath>
+            <xpath expr="//tree//field[@name='price_total']" position="attributes">
+                <attribute name="readonly">sale_order_line_id</attribute>
+            </xpath>
+        </field>
+    </record>
+</odoo>
\ No newline at end of file
diff --git a/sub_product/wizard/__init__.py b/sub_product/wizard/__init__.py
new file mode 100644
index 00000000000..6d701129125
--- /dev/null
+++ b/sub_product/wizard/__init__.py
@@ -0,0 +1,2 @@
+from . import sub_products
+from . import sub_products_line
\ No newline at end of file
diff --git a/sub_product/wizard/sub_products.py b/sub_product/wizard/sub_products.py
new file mode 100644
index 00000000000..896f390ffe0
--- /dev/null
+++ b/sub_product/wizard/sub_products.py
@@ -0,0 +1,56 @@
+from odoo import fields, models, api
+
+
+class SubProducts(models.TransientModel):
+    _name = 'sub.products'
+    _description = "Sub Product"
+
+    name = fields.Char()
+    sub_product_line_ids = fields.One2many('sub.products.line', 'sub_product_id')
+
+    @api.model
+    def default_get(self, fields_list):
+        res = super().default_get(fields_list)
+        active_id = self.env.context.get('active_id')
+        sub_product = self.env['sale.order.line'].search([('sale_order_line_id', '=', active_id)])
+        sale_order_line_current_record = self.env['sale.order.line'].browse(active_id)
+        sub_product_lines = []
+        if len(sub_product) > 0:
+            for product in sub_product:
+                sub_product_lines.append((0, 0, {
+                    'product_id': product.product_id.id,
+                    'quantity': product.product_uom_qty,
+                    'price': product.previously_set_price
+                }))
+        else:
+            for product in sale_order_line_current_record.product_template_id.sub_product_ids:
+                sub_product_lines.append((0, 0, {
+                    'product_id' : product.id,
+                    'quantity': 1.0,
+                    'price': product.lst_price
+                }))
+        res['sub_product_line_ids'] = sub_product_lines
+        return res
+    
+    def action_add_sub_product(self):
+        active_id = self.env.context.get('active_id')
+        sub_product = self.env['sale.order.line'].search([('sale_order_line_id', '=', active_id)])
+        if len(sub_product) > 0:
+            self.env['sale.order.line'].search([('sale_order_line_id', '=', active_id)]).unlink()
+        product_order_line = self.env['sale.order.line'].browse(active_id)
+        new_price_unit = product_order_line.product_id.lst_price
+        for sub_product_line in self.sub_product_line_ids:
+            self.env['sale.order.line'].create(
+                {
+                    'order_id': product_order_line.order_id.id,
+                    'product_id': sub_product_line.product_id.id,
+                    'name': sub_product_line.product_id.name,
+                    'product_uom_qty': sub_product_line.quantity,
+                    'price_unit': 0.0,
+                    'customer_lead': 0.0,
+                    'sale_order_line_id': active_id,
+                    'previously_set_price': sub_product_line.price
+                }
+            )
+            new_price_unit = new_price_unit + sub_product_line.quantity * sub_product_line.price
+        product_order_line.price_unit = new_price_unit
diff --git a/sub_product/wizard/sub_products_line.py b/sub_product/wizard/sub_products_line.py
new file mode 100644
index 00000000000..482b960e945
--- /dev/null
+++ b/sub_product/wizard/sub_products_line.py
@@ -0,0 +1,12 @@
+from odoo import fields, models, api
+
+
+class SubProuctsLine(models.TransientModel):
+    _name = 'sub.products.line'
+    _description = "Sub Product Line"
+
+    sub_product_id = fields.Many2one('sub.products')
+    product_id = fields.Many2one('product.product')
+    product_name = fields.Char(related='product_id.name')
+    quantity = fields.Integer()
+    price = fields.Float(readonly=False, store=True)
diff --git a/sub_product/wizard/sub_products_views.xml b/sub_product/wizard/sub_products_views.xml
new file mode 100644
index 00000000000..ad377c3e277
--- /dev/null
+++ b/sub_product/wizard/sub_products_views.xml
@@ -0,0 +1,35 @@
+<?xml version='1.0' encoding='utf-8'?>
+<odoo>
+    <record id="action_sub_products" model="ir.actions.act_window">
+        <field name="name">Add Sub Product</field>
+        <field name="res_model">sub.products</field>
+        <field name="view_mode">form</field>
+        <field name="target">new</field>
+        <field name="context">{'default_name': context.get('product_name')}</field>
+    </record>
+
+    <record id="sub_products_view_form" model="ir.ui.view">
+        <field name="name">sub.products.view.form</field>
+        <field name="model">sub.products</field>
+        <field name="arch" type="xml">
+            <form>
+                <h4>
+                    <field name="name" readonly='1'/>
+                    Sub Products: 
+                </h4>
+                <field name="sub_product_line_ids">
+                    <tree create='0' editable='1'>
+                        <field name="product_id"/>
+                        <field name="quantity"/>
+                        <field name="price"/>
+                    </tree>
+                </field>
+                <footer>
+                    <button string="Confirm" name="action_add_sub_product" type="object" class="oe_highlight"/>
+                    <button string="Cancel" class="btn btn-secondary" special="cancel"/>
+                </footer>
+            </form>
+        </field>
+    </record>
+
+</odoo>
\ No newline at end of file