|
| 1 | +from odoo import api, exceptions, fields, models |
| 2 | +from datetime import date |
| 3 | +from dateutil.relativedelta import relativedelta |
| 4 | + |
| 5 | + |
| 6 | +class Estate_Property(models.Model): |
| 7 | + _name = "estate_property" |
| 8 | + _description = "Estate properties" |
| 9 | + _order = "id desc" |
| 10 | + active = False |
| 11 | + |
| 12 | + name = fields.Char(required=True, string="Title") |
| 13 | + |
| 14 | + status = fields.Selection( |
| 15 | + [ |
| 16 | + ("new", "New"), |
| 17 | + ("offer_received", "Offer received"), |
| 18 | + ("offer_accepted", "Offer Accepted"), |
| 19 | + ("sold", "Sold"), |
| 20 | + ("canceled", "Canceled"), |
| 21 | + ], |
| 22 | + default="new", |
| 23 | + readonly=True, |
| 24 | + copy=False, |
| 25 | + string="Sale State", |
| 26 | + ) |
| 27 | + |
| 28 | + description = fields.Text(copy=False, string="Description") |
| 29 | + |
| 30 | + postcode = fields.Char( |
| 31 | + help="Une adresse serait mieux mais bon...", string="Postcode" |
| 32 | + ) |
| 33 | + |
| 34 | + date_availability = fields.Date( |
| 35 | + default=(date.today() + relativedelta(months=+3)), |
| 36 | + copy=False, |
| 37 | + string="Available From", |
| 38 | + ) |
| 39 | + |
| 40 | + expected_price = fields.Float( |
| 41 | + default=0.0, required=True, copy=False, string="Expected Price" |
| 42 | + ) |
| 43 | + |
| 44 | + selling_price = fields.Float(readonly=True, string="Selling Price") |
| 45 | + |
| 46 | + bedrooms = fields.Integer(default=2, string="Bedrooms") |
| 47 | + |
| 48 | + living_area = fields.Integer(string="Living Area (sqm)") |
| 49 | + |
| 50 | + facades = fields.Integer(default=2, string="Facades") |
| 51 | + |
| 52 | + garage = fields.Boolean(default=False, string="Garage") |
| 53 | + |
| 54 | + garden = fields.Boolean(default=False, string="Garden") |
| 55 | + |
| 56 | + garden_area = fields.Integer(default=0, string="Garden Area (sqm)") |
| 57 | + |
| 58 | + garden_orientation = fields.Selection( |
| 59 | + [("north", "North"), ("south", "South"), ("west", "West"), ("east", "East")], |
| 60 | + string="Garden Orientation", |
| 61 | + ) |
| 62 | + |
| 63 | + type_id = fields.Many2one( |
| 64 | + "estate_property_type", required=True, string="Property Type" |
| 65 | + ) |
| 66 | + |
| 67 | + buyer = fields.Many2one("res.partner", copy=False, string="Buyer") |
| 68 | + |
| 69 | + salesperson = fields.Many2one( |
| 70 | + "res.users", default=(lambda self: self.env.user), string="Salesman" |
| 71 | + ) |
| 72 | + |
| 73 | + tag_ids = fields.Many2many("estate_property_tag", string="Property Tags") |
| 74 | + |
| 75 | + offer_ids = fields.One2many("estate_property_offer", "property_id", string="Offers") |
| 76 | + |
| 77 | + total_area = fields.Integer(compute="_compute_total_area", string="Total Area") |
| 78 | + |
| 79 | + best_offer = fields.Float( |
| 80 | + compute="_compute_best_offer", default=0.0, string="Best Offer" |
| 81 | + ) |
| 82 | + |
| 83 | + _sql_constraints = [ |
| 84 | + ( |
| 85 | + "check_positive_expected_price", |
| 86 | + "CHECK(expected_price >= 0.0)", |
| 87 | + "Expected Price should be a positive number.", |
| 88 | + ), |
| 89 | + ( |
| 90 | + "check_positive_selling_price", |
| 91 | + "CHECK(selling_price >= 0.0)", |
| 92 | + "Selling Price should be a positive number.", |
| 93 | + ), |
| 94 | + ] |
| 95 | + |
| 96 | + @api.depends("garden_area", "living_area") |
| 97 | + def _compute_total_area(self): |
| 98 | + for record in self: |
| 99 | + record.total_area = record.garden_area + record.living_area |
| 100 | + |
| 101 | + @api.depends("offer_ids") |
| 102 | + def _compute_best_offer(self): |
| 103 | + for record in self: |
| 104 | + record.best_offer = max(record.offer_ids.mapped("price")) |
| 105 | + |
| 106 | + @api.onchange("garden") |
| 107 | + def _onchange_garden(self): |
| 108 | + if self.garden: |
| 109 | + self.garden_area = 10 |
| 110 | + self.garden_orientation = "north" |
| 111 | + else: |
| 112 | + self.garden_area = 0 |
| 113 | + self.garden_orientation = "" |
| 114 | + |
| 115 | + @api.constrains("selling_price", "expected_price") |
| 116 | + def _check_expected_vs_selling_price(self): |
| 117 | + for record in self: |
| 118 | + if (record.selling_price > 0.0) and ( |
| 119 | + record.selling_price < 0.9 * record.expected_price |
| 120 | + ): |
| 121 | + raise exceptions.ValidationError( |
| 122 | + r"Cannot sell for less than 90% of expected price." |
| 123 | + ) |
| 124 | + |
| 125 | + def action_sold(self): |
| 126 | + for record in self: |
| 127 | + if record.status != "canceled": |
| 128 | + record.status = "sold" |
| 129 | + else: |
| 130 | + raise exceptions.UserError("Canceled properties cannot be sold.") |
| 131 | + return True |
| 132 | + |
| 133 | + def action_cancel(self): |
| 134 | + for record in self: |
| 135 | + if record.status != "sold": |
| 136 | + record.status = "canceled" |
| 137 | + else: |
| 138 | + raise exceptions.UserError("Sold properties cannot be canceled.") |
| 139 | + return True |
0 commit comments