Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
18ca504
[ADD] estate: Create Real Estate module manifest
MrRose765 Feb 16, 2026
427542d
[IMP] estate: create estate_property model add basic fields. \n Chapt…
MrRose765 Feb 16, 2026
a1468e3
[IMP] estate: Create access rights for estate property.
MrRose765 Feb 16, 2026
cd2072a
[IMP] estate: Default menus and form view for estate properties.
MrRose765 Feb 17, 2026
808607a
[IMP] estate: Add list,form and search views for estate properties
MrRose765 Feb 17, 2026
36b521e
[IMP] estate: Add property types, tags and offers.
MrRose765 Feb 17, 2026
cce5435
[IMP] estate: Add total_area, best_price and validity date.
MrRose765 Feb 17, 2026
ad97a22
[IMP] estate: Add possibility to sold/cancel property and accept/refu…
MrRose765 Feb 17, 2026
140606d
[IMP] estate: Add constraints on prices and tag/property names.
MrRose765 Feb 18, 2026
b9b4573
[IMP] estate: add constraints and UI improvements
MrRose765 Feb 18, 2026
3b94c34
[IMP] estate: link users to properties and protect deletion
MrRose765 Feb 18, 2026
88da1d4
[ADD] estate_account: Add creation of invoice when a property is sold.
MrRose765 Feb 18, 2026
9231b81
[IMP] estate: Add kanban view for estate properties.
MrRose765 Feb 18, 2026
f65151f
[IMP] awesome_owl: Add counter and todolists components
MrRose765 Feb 20, 2026
81d376b
[IMP] estate: introduce standard and demo data
MrRose765 Feb 23, 2026
a6b1799
[IMP] estate: add managers and user groups with their rules.
MrRose765 Feb 24, 2026
46c3f0a
[IMP] estate: Add constraints and tests on estate properties.
MrRose765 Feb 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions awesome_owl/static/src/card/card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Component, useState } from "@odoo/owl";

export class Card extends Component {
static template = "awesome_owl.Card";
static props = {
title: String,
slots: Object,
}

setup() {
this.state = useState({isOpened: false});
}

expand() {
this.state.isOpened = !this.state.isOpened;
}
}

20 changes: 20 additions & 0 deletions awesome_owl/static/src/card/card.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<templates xml:space="preserve">

<t t-name="awesome_owl.Card">
<div class="card d-inline-block m-2" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">
<t t-out="props.title"/>
<button class="btn btn-primary" t-on-click="expand">
<t t-if="state.isOpened">Collapse</t>
<t t-if="!state.isOpened">Expand</t>
</button>
</h5>
<p class="card-text" t-if="state.isOpened">
<t t-slot="default"/>
</p>
</div>
</div>
</t>
</templates>
18 changes: 18 additions & 0 deletions awesome_owl/static/src/counter/counter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Component, useState } from "@odoo/owl";


export class Counter extends Component {
static template = "awesome_owl.Counter";
static props = {
onChange: {type: Function, optional: true},
}

setup() {
this.state = useState({ value: 1 });
}

increment() {
this.state.value++;
this.props.onChange?.();
}
}
11 changes: 11 additions & 0 deletions awesome_owl/static/src/counter/counter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<templates xml:space="preserve">

<t t-name="awesome_owl.Counter">
<div class="m-2 p-2 border d-inline-block">
<span class="me-2">Counter: <t t-out="state.value"/></span>
<button class="btn btn-primary" t-on-click="increment">Increment</button>
</div>
</t>

</templates>
16 changes: 15 additions & 1 deletion awesome_owl/static/src/playground.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import { Component } from "@odoo/owl";
import { Component, markup, useState } from "@odoo/owl";
import { Counter } from "./counter/counter";
import { Card } from "./card/card";
import { TodoList } from "./todo_list/todo_list";

export class Playground extends Component {
static template = "awesome_owl.playground";
static components = { Counter, Card, TodoList };

setup() {
this.value1 = "<div class='text-danger'>Hello</div>";
this.value2 = markup("<img src='x' onerror='alert(1)'/>");
this.sum = useState({ value: 2 });
}

incrementSum() {
this.sum.value++;
}
}
16 changes: 14 additions & 2 deletions awesome_owl/static/src/playground.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,21 @@
<templates xml:space="preserve">

<t t-name="awesome_owl.playground">
<div class="p-3">
hello world
<div class="p-3 border d-inline-block">
<Counter onChange.bind="this.incrementSum"/>
<Counter onChange.bind="this.incrementSum"/>
<p class="mt-2">Sum: <t t-out="sum.value"/></p>
</div>

<div>
<Card title="'Card 1'">
Card 1 content.
</Card>
<Card title="'Card 2'">
<Counter/>
</Card>
</div>
<TodoList/>
</t>

</templates>
26 changes: 26 additions & 0 deletions awesome_owl/static/src/todo_list/todo_item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {Component} from "@odoo/owl";

export class TodoItem extends Component {
static template = "awesome_owl.TodoItem";
static props = {
todo: {
type: Object,
shape: {
id: Number,
description: String,
isCompleted: Boolean,
}
},
toggleState: Function,
removeTodo: Function,
};

onChange() {
this.props.toggleState(this.props.todo.id);
}

onRemove() {
this.props.removeTodo(this.props.todo.id);
}

}
20 changes: 20 additions & 0 deletions awesome_owl/static/src/todo_list/todo_item.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="awesome_owl.TodoItem">
<div class="form-check">

<input class="form-check-input"
type="checkbox"
t-att-id="props.todo.id"
t-att-checked="props.todo.isCompleted"
t-on-change="onChange"/>

<label t-att-class="props.todo.isCompleted ? 'text-decoration-line-through text-muted' : '' "
t-att-for="props.todo.id">
<t t-out="props.todo.id"/>. <t t-out="props.todo.description"/>
</label>

<span class="fa fa-remove text-danger ms-2" t-on-click="onRemove"/>
</div>
</t>
</templates>
39 changes: 39 additions & 0 deletions awesome_owl/static/src/todo_list/todo_list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {Component, useState} from "@odoo/owl";
import {TodoItem} from "./todo_item";
import {useAutoFocus} from "../utils";

export class TodoList extends Component {
static template = "awesome_owl.TodoList";
static components = {TodoItem};

setup() {
this.currId = 1;
this.todos = useState([]);
useAutoFocus("input_todo");
}

addTodo(ev) {
if (ev.keyCode === 13 && ev.target.value !== "") {
this.todos.push({
id: this.currId++,
description: ev.target.value,
isCompleted: false
});
ev.target.value = "";
}
}

toggleTodo(id) {
const todo = this.todos.find(todo => todo.id === id);
if (todo) {
todo.isCompleted = !todo.isCompleted;
}
}

removeTodo(id) {
const index = this.todos.findIndex(todo => todo.id === id);
if (index >= 0) {
this.todos.splice(index, 1);
}
}
}
12 changes: 12 additions & 0 deletions awesome_owl/static/src/todo_list/todo_list.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="awesome_owl.TodoList">
<div class="d-inline-block border p-2 m-2">
<input class="form-control mb-3" type="text" placeholder="Add a todo !" t-on-keyup="addTodo" t-ref="input_todo"/>
<p t-if="todos.length === 0">No todos yet !</p>
<t t-foreach="todos" t-as="todo" t-key="todo.id">
<TodoItem todo="todo" toggleState.bind="toggleTodo" removeTodo.bind="removeTodo"/>
</t>
</div>
</t>
</templates>
8 changes: 8 additions & 0 deletions awesome_owl/static/src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {onMounted, useRef} from "@odoo/owl";

export function useAutoFocus(refName) {
const ref = useRef(refName);
onMounted(() => {
ref.el.focus();
});
}
1 change: 1 addition & 0 deletions estate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
29 changes: 29 additions & 0 deletions estate/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
'name': 'Real Estate',
'version': '1.0',
'category': 'Real Estate/Brokerage',
'summary': 'Manage your real estate properties and offers',
'author': 'Odoo S.A.',
'license': 'LGPL-3',
'depends': [
'base',
],
'data': [
'security/estate_security.xml',
'security/ir.model.access.csv',
'views/estate_property_views.xml',
'views/estate_property_offer_views.xml',
'views/estate_property_type_views.xml',
'views/estate_property_tag_views.xml',
'views/res_users_views.xml',
'views/estate_menus.xml',
'data/estate.property.type.csv',
],
'demo': [
'demo/estate_property_demo.xml',
'demo/estate_property_offer_demo.xml',
],
'installable': True,
'application': True,
'auto_install': False,
}
5 changes: 5 additions & 0 deletions estate/data/estate.property.type.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"id","name","sequence"
estate_property_type_residential,Residential,1
estate_property_type_commercial,Commercial,2
estate_property_type_industrial,Industrial,3
estate_property_type_land,Land,4
58 changes: 58 additions & 0 deletions estate/demo/estate_property_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="demo_estate_property_1" 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="property_type_id" ref="estate_property_type_residential"/>
<field name="postcode">12345</field>
<field name="date_availability">2020-02-02</field>
<field name="expected_price">1500000</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>
</record>
<record id="demo_estate_property_2" model="estate.property">
<field name="name">Trailer home</field>
<field name="state">canceled</field>
<field name="description">Home in a trailer park</field>
<field name="property_type_id" ref="estate_property_type_residential"/>
<field name="postcode">54321</field>
<field name="date_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>
</record>
<record id="demo_estate_property_3" model="estate.property">
<field name="name">Small Apartment</field>
<field name="state">new</field>
<field name="description">A small apartment in the city center</field>
<field name="property_type_id" ref="estate_property_type_industrial"/>
<field name="postcode">98765</field>
<field name="date_availability">2020-01-01</field>
<field name="expected_price">500000</field>
<field name="bedrooms">2</field>
<field name="living_area">50</field>
<field name="facades">2</field>
<field name="offer_ids" eval="[
Command.create({
'price': 450000,
'partner_id': ref('base.res_partner_12'),
'date_deadline': datetime.now() + timedelta(days=14),
}),
Command.create({
'price': 550000,
'partner_id': ref('base.res_partner_3'),
'date_deadline': datetime.now() + timedelta(days=14),
}),
]"/>
</record>
</data>
</odoo>
26 changes: 26 additions & 0 deletions estate/demo/estate_property_offer_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<record id="demo_estate_property_offer_1" model="estate.property.offer">
<field name="price">10000</field>
<field name="partner_id" ref="base.res_partner_12"/>
<field name="property_id" ref="demo_estate_property_1"/>
<field name="date_deadline" eval="datetime.now() + timedelta(days=14)"/>
</record>
<record id="demo_estate_property_offer_2" model="estate.property.offer">
<field name="price">1500000</field>
<field name="partner_id" ref="base.res_partner_12"/>
<field name="property_id" ref="demo_estate_property_1"/>
<field name="date_deadline" eval="datetime.now() + timedelta(days=14)"/>
</record>
<record id="demo_estate_property_offer_3" model="estate.property.offer">
<field name="price">1500001</field>
<field name="partner_id" ref="base.res_partner_3"/>
<field name="property_id" ref="demo_estate_property_1"/>
<field name="date_deadline" eval="datetime.now() + timedelta(days=14)"/>
</record>

<function model="estate.property.offer" name="action_accept_offer" eval="[ref('demo_estate_property_offer_2')]"/>
</data>

</odoo>
7 changes: 7 additions & 0 deletions estate/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from . import (
estate_property,
estate_property_offer,
estate_property_tag,
estate_property_type,
res_users,
)
Loading