Skip to content

Commit b0fb6e3

Browse files
committed
[ADD] real_estate: generate pdf report for offers and offer demo data
Implemented PDF report generation for property offers using QWeb templates. Created a new report template to display offer details in a printable format. Added demo data for offers to simulate real scenarios and support testing. Ensured demo offers are linked to existing demo properties and partners.
1 parent 513c8e3 commit b0fb6e3

19 files changed

+391
-123
lines changed

estate_account/models/estate_property.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from odoo import models, Command
1+
from odoo import Command, models
22
from odoo.exceptions import UserError
33

44

@@ -18,6 +18,11 @@ def action_sold(self):
1818
if not record.selling_price:
1919
raise UserError("Please set a Selling Price before generating an invoice.")
2020

21+
journal = self.env['account.journal'].sudo().search([('type', '=', 'sale')], limit=1)
22+
if not journal:
23+
raise UserError("No sale journal found. Please configure at least one sale journal.")
24+
record.check_access_rights('write')
25+
record.check_access_rule('write')
2126
invoice_vals = {
2227
"partner_id": record.buyer_id.id,
2328
"move_type": "out_invoice",
@@ -36,5 +41,5 @@ def action_sold(self):
3641
]
3742
}
3843

39-
self.env["account.move"].create(invoice_vals)
44+
self.env["account.move"].sudo().create(invoice_vals)
4045
return res

real_estate/__manifest__.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,29 @@
22
'name': 'estate',
33
'version': '1.0.0',
44
'author': 'rodh',
5-
'category': 'Real Estate',
65
'summary': 'Manage real estate properties and transactions',
76
'depends': [
87
'base',
98
],
109
'application': True,
1110
'installable': True,
1211
'license': 'LGPL-3',
12+
'category': 'Real Estate/Brokerage',
1313
'data': [
14-
'security/ir.model.access.csv',
15-
'view/estate_property_views.xml',
16-
'view/estate_property_offer_views.xml',
17-
'view/estate_property_type_views.xml',
18-
'view/estate_property_tag_views.xml',
19-
'view/estate_res_users_view.xml',
20-
'view/estate_menu.xml',
14+
'security/security.xml',
15+
'security/ir.model.access.csv',
16+
'security/record_rules.xml',
17+
'view/estate_property_views.xml',
18+
'view/estate_property_offer_views.xml',
19+
'view/estate_property_type_views.xml',
20+
'view/estate_property_tag_views.xml',
21+
'view/estate_res_users_view.xml',
22+
'data/estate.property.type.csv',
23+
'view/estate_menu.xml',
24+
'report/estate_property_templates.xml',
25+
'report/estate_property_reports.xml',
26+
],
27+
'demo': [
28+
'demo/demo_data.xml',
2129
],
2230
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
id,name
2+
estate_property_type_residential,Residential
3+
estate_property_type_commercial,Commercial
4+
estate_property_type_industrial,Industrial
5+
estate_property_type_land,Land

real_estate/demo/demo_data.xml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<odoo>
3+
<record id="property_demo_big_villa" model="estate.property">
4+
<field name="name">Big Villa</field>
5+
<field name="state">new</field>
6+
<field name="description">A nice and big villa</field>
7+
<field name="postcode">a</field>
8+
<field name="availability_date">2020-02-02</field>
9+
<field name="expected_price">16000.0</field>
10+
<field name="selling_price">15900.0</field>
11+
<field name="bedrooms">6</field>
12+
<field name="living_area">100.0</field>
13+
<field name="facades">4</field>
14+
<field name="garage" eval="True"/>
15+
<field name="garden" eval="True"/>
16+
<field name="garden_area">100000.0</field>
17+
<field name="garden_orientation">south</field>
18+
<field name="property_type_id" ref="real_estate.estate_property_type_residential"/>
19+
</record>
20+
<record id="property_demo_trailer_home" model="estate.property">
21+
<field name="name">Trailer home</field>
22+
<field name="state">new</field>
23+
<field name="description">Home in a trailer park</field>
24+
<field name="postcode">a</field>
25+
<field name="availability_date">1970-01-01</field>
26+
<field name="expected_price">10000.0</field>
27+
<field name="selling_price">15000.0</field>
28+
<field name="bedrooms">2</field>
29+
<field name="living_area">10.0</field>
30+
<field name="facades">4</field>
31+
<field name="garage" eval="True"/>
32+
<field name="garden" eval="True"/>
33+
<field name="property_type_id" ref="real_estate.estate_property_type_residential"/>
34+
</record>
35+
<record id="offer_demo_1" model="estate.property.offer">
36+
<field name="partner_id" ref="base.res_partner_12"/>
37+
<field name="price">15800.00</field>
38+
<field name="validity">14</field>
39+
<field name="property_id" ref="property_demo_big_villa"/>
40+
<field name="date_deadline" eval="(datetime.today() + timedelta(days=14)).strftime('%Y-%m-%d')"/>
41+
</record>
42+
<record id="offer_demo_2" model="estate.property.offer">
43+
<field name="partner_id" ref="base.res_partner_12"/>
44+
<field name="price">16800.00</field>
45+
<field name="validity">14</field>
46+
<field name="property_id" ref="property_demo_big_villa"/>
47+
<field name="date_deadline" eval="(datetime.today() + timedelta(days=14)).strftime('%Y-%m-%d')"/>
48+
</record>
49+
<record id="offer_demo_3" model="estate.property.offer">
50+
<field name="partner_id" ref="base.res_partner_3"/>
51+
<field name="price">17800.00</field>
52+
<field name="validity">14</field>
53+
<field name="property_id" ref="property_demo_big_villa"/>
54+
<field name="date_deadline" eval="(datetime.today() + timedelta(days=14)).strftime('%Y-%m-%d')"/>
55+
</record>
56+
<function model="estate.property.offer" name="action_accept">
57+
<value eval="[ref('offer_demo_2')]"/>
58+
</function>
59+
<function model="estate.property.offer" name="action_refuse">
60+
<value eval="[ref('offer_demo_1'), ref('offer_demo_3')]"/>
61+
</function>
62+
<record id="property_demo_modern_apartment" model="estate.property">
63+
<field name="name">Modern Apartment</field>
64+
<field name="postcode">a</field>
65+
<field name="state">new</field>
66+
<field name="expected_price">900000.0</field>
67+
<field name="selling_price">920000.0</field>
68+
<field name="living_area">85.0</field>
69+
<field name="bedrooms">3</field>
70+
<field name="offer_ids" eval="[
71+
Command.create({
72+
'price': 1000000.0,
73+
'validity': 14,
74+
'partner_id': ref('base.res_partner_12'),
75+
'date_deadline': (datetime.today() + timedelta(days=14)).strftime('%Y-%m-%d')
76+
}),
77+
Command.create({
78+
'price': 1000000.0,
79+
'validity': 14,
80+
'partner_id': ref('base.res_partner_3'),
81+
'date_deadline': (datetime.today() + timedelta(days=14)).strftime('%Y-%m-%d')
82+
})
83+
]"/>
84+
</record>
85+
</odoo>

real_estate/models/estate_property.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ class EstateProperty(models.Model):
5454
tag_ids = fields.Many2many('estate.property.tag', string="Tags")
5555
offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers")
5656
best_price = fields.Float(string="Best Offer", compute="_compute_best_price")
57+
company_id = fields.Many2one(
58+
'res.company',
59+
string='Company',
60+
default=lambda self: self.env.company
61+
)
5762

5863
@api.constrains('selling_price', 'expected_price')
5964
def _check_selling_price(self):

real_estate/models/estate_property_tag.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from odoo import models, fields
1+
from odoo import fields, models
22

33

44
class EstatePropertyTag(models.Model):

real_estate/models/estate_property_type.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from odoo import models, fields, api
1+
from odoo import api, fields, models
22

33

44
class EstatePropertyType(models.Model):

real_estate/models/estate_res_users.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from odoo import models, fields
1+
from odoo import fields, models
22

33

44
class ResUsers(models.Model):
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<odoo>
3+
<record id="report_estate_property_offer" model="ir.actions.report">
4+
<field name="name">Print Offers</field>
5+
<field name="model">estate.property</field>
6+
<field name="report_type">qweb-pdf</field>
7+
<field name="report_name">real_estate.report_property_offers</field>
8+
<field name="report_file">real_estate.report_property_offers</field>
9+
<field name="print_report_name">'Property Offers - %s' % (object.name).replace('/', '')</field>
10+
<field name="binding_model_id" ref="model_estate_property"/>
11+
</record>
12+
<record id="report_res_users_properties" model="ir.actions.report">
13+
<field name="name">Print Properties</field>
14+
<field name="model">res.users</field>
15+
<field name="report_type">qweb-pdf</field>
16+
<field name="report_name">real_estate.report_salesman_properties</field>
17+
<field name="report_file">real_estate.report_salesman_properties</field>
18+
<field name="print_report_name">'Properties - %s' % (object.name).replace('/','')</field>
19+
<field name="binding_model_id" ref="base.model_res_users"/>
20+
</record>
21+
</odoo>
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<odoo>
3+
<template id="report_property_offers">
4+
<t t-call="web.html_container">
5+
<t t-foreach="docs" t-as="property">
6+
<t t-call="web.external_layout">
7+
<div class="page">
8+
<h2>
9+
<span t-esc="property.name"/>
10+
</h2>
11+
<p>
12+
<strong>Salesman:</strong>
13+
<span t-field="property.salesperson_id"/>
14+
</p>
15+
<t t-call="real_estate.property_offer_table_sub">
16+
<t t-set="property" t-value="property"/>
17+
</t>
18+
</div>
19+
</t>
20+
</t>
21+
</t>
22+
</template>
23+
<template id="property_offer_table_sub">
24+
<t t-if="property.offer_ids">
25+
<p>
26+
<strong>Expected Price:</strong>
27+
<span t-field="property.expected_price"/>
28+
</p>
29+
<p>
30+
<strong>Status:</strong>
31+
<span t-field="property.state"/>
32+
</p>
33+
<table class="table table-sm mt32" style="width:100%;">
34+
<thead>
35+
<tr>
36+
<th>Price</th>
37+
<th>Partner</th>
38+
<th>Validity (days)</th>
39+
<th>Deadline</th>
40+
<th>Status</th>
41+
</tr>
42+
</thead>
43+
<tbody>
44+
<tr t-foreach="property.offer_ids" t-as="offer">
45+
<td>
46+
<span t-field="offer.price" />
47+
</td>
48+
<td>
49+
<span t-field="offer.partner_id.name" />
50+
</td>
51+
<td>
52+
<span t-field="offer.validity" />
53+
</td>
54+
<td>
55+
<span t-field="offer.date_deadline" />
56+
</td>
57+
<td>
58+
<span t-field="offer.state" />
59+
</td>
60+
</tr>
61+
</tbody>
62+
</table>
63+
</t>
64+
<t t-else="">
65+
<p>
66+
<em>No offers available for this property.</em>
67+
</p>
68+
</t>
69+
</template>
70+
<template id="report_salesman_properties">
71+
<t t-foreach="docs" t-as="salesman">
72+
<t t-call="web.html_container">
73+
<t t-call="web.external_layout">
74+
<div class="page">
75+
<h2>
76+
<strong>Salesman: </strong>
77+
<span t-field="salesman.name"/>
78+
</h2>
79+
<t t-if="salesman.property_ids">
80+
<t t-set="properties" t-value="salesman.property_ids" />
81+
<t t-foreach="properties" t-as="property">
82+
<h3>
83+
<span t-field="property.name"/>
84+
</h3>
85+
<t t-call="real_estate.property_offer_table_sub">
86+
<t t-set="property" t-value="property"/>
87+
</t>
88+
</t>
89+
</t>
90+
<strong t-else="">No properties found :</strong>
91+
</div>
92+
</t>
93+
</t>
94+
</t>
95+
</template>
96+
<template id="report_estate_property_invoice_info" inherit_id="real_estate.report_property_offers">
97+
<xpath expr="//div[hasclass('page')]" position="inside">
98+
<t t-if="property.state == 'sold'">
99+
<div class="mt-3">
100+
<p>
101+
<strong>Invoice Information:</strong>
102+
<br />
103+
invoice has been generated for the customer. </p>
104+
</div>
105+
</t>
106+
</xpath>
107+
</template>
108+
</odoo>

0 commit comments

Comments
 (0)