Skip to content

Commit 2619f5c

Browse files
[IMP] booking_engine: city tax widget
- Add a widget to help user to compute the number of city tax computation to be delivered . - Adjust the "Check guests out" knowledge section with below input in the dependent industries. task-4978627 closes #1215 Signed-off-by: Vallaeys Valentin (vava) <[email protected]>
1 parent b95a298 commit 2619f5c

File tree

17 files changed

+380
-277
lines changed

17 files changed

+380
-277
lines changed

booking_engine/__manifest__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
'name': 'Booking Engine',
3-
'version': '1.0',
3+
'version': '1.1',
44
'category': 'Hidden/Tools',
55
'author': 'Odoo S.A.',
66
'depends': [
@@ -15,6 +15,8 @@
1515
],
1616
'data': [
1717
'data/res_config_settings.xml',
18+
'data/ir_model.xml',
19+
'data/ir_model_access.xml',
1820
'data/ir_model_fields.xml',
1921
'data/account_tax.xml',
2022
'data/product_template.xml',

booking_engine/data/base_automation.xml

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,8 @@
11
<?xml version='1.0' encoding='UTF-8'?>
22
<odoo>
3-
<record id="industry_on_so_line" model="base.automation">
4-
<field name="model_id" ref="sale.model_sale_order"/>
5-
<field name="action_server_ids" eval="[(6, 0, [ref('industry_add_update')])]"/>
6-
<field name="trigger">on_create_or_write</field>
7-
<field name="name">On SO line edit, add/edit city tax</field>
8-
<field name="trigger_field_ids" eval="[(6, 0, [ref('sale_model_sale_order_x_picked_up')])]"/>
9-
<field name="filter_pre_domain">[('x_picked_up', '=', False)]</field>
10-
<field name="filter_domain">[('x_picked_up', '=', True)]</field>
11-
</record>
123
<record id="industry_on_slot_fix_times" model="base.automation">
134
<field name="model_id" ref="planning.model_planning_slot"/>
14-
<field name="action_server_ids" eval="[(6, 0, [ref('industry_fix_slot_times'), ref('industry_trigger_so_update_from_slot')])]"/>
5+
<field name="action_server_ids" eval="[(6, 0, [ref('industry_fix_slot_times')])]"/>
156
<field name="trigger">on_create_or_write</field>
167
<field name="name">Fix Slot Times</field>
178
<field name="trigger_field_ids" eval="[(6, 0, [ref('planning.field_planning_slot__end_datetime'), ref('planning.field_planning_slot__start_datetime'), ref('sale_planning.field_planning_slot__sale_line_id')])]"/>
Lines changed: 54 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,52 @@
11
<?xml version='1.0' encoding='UTF-8'?>
22
<odoo>
3-
<record id="industry_add_update" model="ir.actions.server">
3+
<record id="update_city_tax_action" model="ir.actions.server">
44
<field name="name">Add/Update City Tax</field>
5-
<field name="model_id" ref="sale.model_sale_order"/>
6-
<field name="usage">base_automation</field>
5+
<field name="model_id" ref="x_model_city_tax"/>
76
<field name="state">code</field>
8-
<field name="code"><![CDATA[for record in records:
9-
stay_taxes = 0
10-
stay_tax_line = False
11-
for so_line in record.order_line:
12-
if so_line.product_id.x_is_a_room_offer:
13-
if so_line.x_nights > 0: stay_taxes += so_line.x_nights
14-
if so_line.product_id.x_is_stay_tax: stay_tax_line = so_line
15-
if stay_taxes > 0:
16-
if stay_tax_line: stay_tax_line['product_uom_qty'] = stay_taxes
17-
else: # Add stay tax product
18-
product = env['product.product'].search([('x_is_stay_tax', '=', True)], limit=1)
19-
env['sale.order.line'].create({'order_id': record.id, 'product_id': product.id, 'product_uom_qty': stay_taxes})
7+
<field name="code"><![CDATA[
8+
stay_tax_line = False
9+
sequence = 0
10+
for so_line in record.x_sale_order_id.order_line:
11+
if so_line.product_id.x_is_stay_tax: stay_tax_line = so_line
12+
sequence = max(sequence, so_line.sequence)
13+
if stay_tax_line: stay_tax_line.write({'product_uom_qty': record.x_total, 'qty_delivered': record.x_total, 'sequence': 1 + sequence})
14+
elif record.x_total > 0:
15+
product = env['product.product'].search([('x_is_stay_tax', '=', True)], limit=1)
16+
env['sale.order.line'].create({'order_id': record.x_sale_order_id.id, 'product_id': product.id, 'product_uom_qty': record.x_total, 'qty_delivered': record.x_total})
2017
]]></field>
2118
</record>
22-
<record id="industry_trigger_so_update_from_slot" model="ir.actions.server">
23-
<field name="name">Trigger SO Update from Slot</field>
24-
<field name="model_id" ref="planning.model_planning_slot"/>
25-
<field name="usage">base_automation</field>
19+
<record id="open_x_city_tax_action" model="ir.actions.server">
20+
<field name="name">Open City Tax</field>
21+
<field name="model_id" ref="sale.model_sale_order"/>
2622
<field name="state">code</field>
2723
<field name="code"><![CDATA[
28-
sale_order = record.sale_order_id
29-
if sale_order:
30-
stay_taxes = 0
31-
stay_tax_line = False
32-
for so_line in sale_order.order_line:
33-
if so_line.product_id.x_is_a_room_offer:
34-
if so_line.x_nights > 0:
35-
stay_taxes += so_line.x_nights
36-
if so_line.product_id.x_is_stay_tax:
37-
stay_tax_line = so_line
38-
if stay_taxes > 0:
39-
if stay_tax_line:
40-
stay_tax_line['product_uom_qty'] = stay_taxes
24+
record.order_line.planning_slot_ids['x_guests'] = len(record.x_guests) // (len(record.order_line.planning_slot_ids) or 1) or 1
25+
action = {
26+
'type': 'ir.actions.act_window',
27+
'name': 'City tax',
28+
'res_model': 'x_city_tax',
29+
'view_mode': 'form',
30+
'target': 'new',
31+
'context': {'search_default_x_sale_order_id': record.id, 'default_x_sale_order_id': record.id},
32+
'domain': [('x_sale_order_id', '=', record.id)],
33+
}
4134
]]></field>
4235
</record>
43-
<record id="industry_fix_slot_times" model="ir.actions.server">
44-
<field name="binding_model_id" ref="planning.model_planning_slot"/>
45-
<field name="model_id" ref="planning.model_planning_slot"/>
46-
<field name="usage">base_automation</field>
47-
<field name="state">code</field>
48-
<field name="name">Fix Slot Times</field>
49-
<field name="code"><![CDATA[def ceil(x):
50-
return int(x) if x == int(x) else int(x) + 1
36+
<record id="industry_fix_slot_times" model="ir.actions.server">
37+
<field name="binding_model_id" ref="planning.model_planning_slot"/>
38+
<field name="model_id" ref="planning.model_planning_slot"/>
39+
<field name="usage">base_automation</field>
40+
<field name="state">code</field>
41+
<field name="name">Fix Slot Times</field>
42+
<field name="code"><![CDATA[
5143
pickup_time = env.ref('sale_renting.recurrence_nightly').pickup_time
5244
return_time = env.ref('sale_renting.recurrence_nightly').return_time
53-
start_datetime = record.start_datetime.astimezone(tz=dateutil.tz.UTC)
54-
end_datetime = record.end_datetime.astimezone(tz=dateutil.tz.UTC)
5545
tz = env.ref('website.default_website').tz
56-
if record.role_id.x_is_a_room_offer:
46+
for record in records:
47+
if not record.role_id.x_is_a_room_offer: continue
48+
start_datetime = record.start_datetime.astimezone(tz=dateutil.tz.UTC)
49+
end_datetime = record.end_datetime.astimezone(tz=dateutil.tz.UTC)
5750
if record.start_datetime and str(record.start_datetime.time()) != f"{int(pickup_time):02d}:{int(pickup_time % 1 * 60):02d}:00":
5851
start = timezone(tz).localize(datetime.datetime(year=start_datetime.year, month=start_datetime.month, day=start_datetime.day, hour=int(pickup_time), minute=int(pickup_time % 1 * 60), second=0))
5952
start_datetime = start.astimezone(tz=dateutil.tz.UTC)
@@ -66,12 +59,10 @@ if record.role_id.x_is_a_room_offer:
6659
end_datetime = end_datetime + datetime.timedelta(days=1)
6760
record['start_datetime'] = start_datetime.replace(tzinfo=None)
6861
record['end_datetime'] = end_datetime.replace(tzinfo=None)
69-
if record.sale_line_id:
62+
for record in records:
7063
nights = 0
7164
if record.sale_line_id.planning_slot_ids:
72-
for slot in record.sale_line_id.planning_slot_ids:
73-
if slot.start_datetime and slot.end_datetime:
74-
nights += ceil((slot.end_datetime - slot.start_datetime).total_seconds() / (24 * 3600))
65+
nights = sum(record.sale_line_id.planning_slot_ids.mapped('x_nights'))
7566
record.sale_line_id.update({
7667
'start_date': record.start_datetime,
7768
'return_date': record.end_datetime,
@@ -91,14 +82,24 @@ return_time = env.ref('sale_renting.recurrence_nightly').return_time
9182
for record in records:
9283
tz = env.ref('website.default_website').tz
9384
rental_start_date = record.rental_start_date.astimezone(tz=dateutil.tz.gettz(tz))
85+
start = rental_start_date.replace(hour=int(pickup_time), minute=int(pickup_time % 1 * 60), second=0)
86+
record['rental_start_date'] = start.astimezone(tz=dateutil.tz.UTC).replace(tzinfo=None)
87+
9488
rental_return_date = record.rental_return_date.astimezone(tz=dateutil.tz.gettz(tz))
95-
start = rental_start_date.replace(hour=int(pickup_time), minute=int(pickup_time % 1 * 60), second=0, microsecond=0)
96-
start_datetime = start.astimezone(tz=dateutil.tz.UTC)
97-
record['rental_start_date'] = start_datetime.replace(tzinfo=None)
98-
end = rental_return_date.replace(hour=int(return_time), minute=int(return_time % 1 * 60), second=0, microsecond=0)
99-
end_datetime = end.astimezone(tz=dateutil.tz.UTC)
100-
record['rental_return_date'] = end_datetime.replace(tzinfo=None)
89+
end = rental_return_date.replace(hour=int(return_time), minute=int(return_time % 1 * 60), second=0)
90+
record['rental_return_date'] = end.astimezone(tz=dateutil.tz.UTC).replace(tzinfo=None)
10191
record.action_update_rental_prices()
92+
]]></field>
93+
</record>
94+
<record id="apply_rental_check_out" model="ir.actions.server">
95+
<field name="name">Apply Rental Checkout</field>
96+
<field name="model_id" ref="sale_renting.model_rental_order_wizard"/>
97+
<field name="state">code</field>
98+
<field name="code"><![CDATA[
99+
record.apply()
100+
if record.order_id.rental_status == "returned":
101+
server_action = record.env['ir.actions.server'].browse(record.env.ref('booking_engine.open_x_city_tax_action').id)
102+
action = server_action.with_context(active_id=record.order_id.id, active_model="sale.order").sudo().run()
102103
]]></field>
103104
</record>
104105
</odoo>

booking_engine/data/ir_model.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<odoo>
3+
<record id="x_model_city_tax" model="ir.model">
4+
<field name="name">City tax</field>
5+
<field name="model">x_city_tax</field>
6+
<field name="transient" eval="True" />
7+
</record>
8+
</odoo>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<odoo>
3+
<record id="city_tax_access" model="ir.model.access">
4+
<field name="group_id" ref="base.group_user"/>
5+
<field name="model_id" ref="x_model_city_tax"/>
6+
<field name="name">x_city_tax_user_access</field>
7+
<field name="perm_create" eval="True"/>
8+
<field name="perm_read" eval="True"/>
9+
<field name="perm_unlink" eval="True"/>
10+
<field name="perm_write" eval="True"/>
11+
</record>
12+
</odoo>

booking_engine/data/ir_model_fields.xml

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@
8484
record['x_identity_check'] = 'na'
8585
elif record.x_nationality and record.x_document_type and record.x_document_number:
8686
record['x_identity_check'] = 'ok'
87-
else:
88-
record['x_identity_check'] = 'invalid'
87+
else: record['x_identity_check'] = 'invalid'
8988
]]></field>
9089
</record>
9190
<record id="product_model_product_template_x_is_a_room_offer_field" model="ir.model.fields">
@@ -115,8 +114,8 @@
115114
<field name="field_description">Order Involves Room</field>
116115
<field name="model_id" ref="sale.model_sale_order"/>
117116
<field name="name">x_order_involves_room</field>
118-
<field name="compute"><![CDATA[for record in self:
119-
record['x_order_involves_room'] = any(line.product_id.x_is_a_room_offer for line in record.order_line)
117+
<field name="compute"><![CDATA[
118+
for record in self: record['x_order_involves_room'] = any(line.product_id.x_is_a_room_offer for line in record.order_line)
120119
]]></field>
121120
<field name="depends">order_line</field>
122121
</record>
@@ -135,8 +134,8 @@
135134
<field name="depends">order_line.qty_delivered</field>
136135
</record>
137136
<record id="res_partner_x_guests_count" model="ir.model.fields">
138-
<field name="compute"><![CDATA[for record in self:
139-
record['x_guests_count'] = self.env['sale.order'].search_count([('x_guests', '=', record.id)])
137+
<field name="compute"><![CDATA[
138+
for record in self: record['x_guests_count'] = self.env['sale.order'].search_count([('x_guests', '=', record.id)])
140139
]]></field>
141140
<field name="ttype">integer</field>
142141
<field name="field_description">Guests count</field>
@@ -162,9 +161,8 @@
162161
<field name="relation">res.partner</field>
163162
<field name="readonly" eval="True"/>
164163
<field name="depends">x_ongoing_booking.partner_id</field>
165-
<field name="compute"><![CDATA[for record in self:
166-
booking = record.x_ongoing_booking
167-
record['x_occupant'] = booking[:1].partner_id.id
164+
<field name="compute"><![CDATA[
165+
for record in self: record['x_occupant'] = record.x_ongoing_booking[:1].partner_id.id
168166
]]></field>
169167
</record>
170168
<record id="res_partner_x_ongoing_bookings" model="ir.model.fields">
@@ -176,4 +174,63 @@
176174
<field name="readonly" eval="True"/>
177175
<field name="name">x_ongoing_bookings</field>
178176
</record>
177+
<record id="model_planning_slot_x_nights" model="ir.model.fields">
178+
<field name="ttype">integer</field>
179+
<field name="field_description">Nights</field>
180+
<field name="model_id" ref="planning.model_planning_slot"/>
181+
<field name="depends">start_datetime, end_datetime</field>
182+
<field name="name">x_nights</field>
183+
<field name="compute"><![CDATA[
184+
for record in self: record['x_nights'] = ((record.end_datetime - record.start_datetime).total_seconds() + 86399) // 86400
185+
]]></field>
186+
</record>
187+
<record id="model_planning_slot_x_guests" model="ir.model.fields">
188+
<field name="ttype">integer</field>
189+
<field name="field_description">Guests</field>
190+
<field name="model_id" ref="planning.model_planning_slot"/>
191+
<field name="name">x_guests</field>
192+
</record>
193+
<record id="model_planning_slot_x_city_tax" model="ir.model.fields">
194+
<field name="ttype">integer</field>
195+
<field name="field_description">City tax count</field>
196+
<field name="model_id" ref="planning.model_planning_slot"/>
197+
<field name="depends">x_nights, x_guests</field>
198+
<field name="name">x_city_tax</field>
199+
<field name="compute"><![CDATA[
200+
for record in self: record['x_city_tax'] = record.x_nights * record.x_guests
201+
]]></field>
202+
</record>
203+
<record id="x_model_city_tax_x_sale_order_id" model="ir.model.fields">
204+
<field name="ttype">many2one</field>
205+
<field name="field_description">Sale order</field>
206+
<field name="model_id" ref="x_model_city_tax"/>
207+
<field name="relation">sale.order</field>
208+
<field name="name">x_sale_order_id</field>
209+
<field name="readonly" eval="True"/>
210+
</record>
211+
<record id="x_model_city_tax_x_slot_ids" model="ir.model.fields">
212+
<field name="ttype">many2many</field>
213+
<field name="field_description">Slots</field>
214+
<field name="model_id" ref="x_model_city_tax"/>
215+
<field name="relation">planning.slot</field>
216+
<field name="depends">x_sale_order_id.order_line.planning_slot_ids</field>
217+
<field name="name">x_slot_ids</field>
218+
<field name="compute"><![CDATA[
219+
for record in self: record['x_slot_ids'] = record.x_sale_order_id.order_line.planning_slot_ids
220+
]]></field>
221+
<field name="store" eval="False"/>
222+
</record>
223+
<record id="x_model_city_tax_x_total" model="ir.model.fields">
224+
<field name="ttype">integer</field>
225+
<field name="field_description">Total</field>
226+
<field name="model_id" ref="x_model_city_tax"/>
227+
<field name="relation_field">planning_total</field>
228+
<field name="name">x_total</field>
229+
<field name="depends">x_slot_ids, x_slot_ids.x_city_tax</field>
230+
<field name="compute"><![CDATA[
231+
for record in self: record['x_total'] = sum(record.x_slot_ids.mapped('x_city_tax'))
232+
]]></field>
233+
<field name="readonly" eval="True"/>
234+
<field name="store" eval="False"/>
235+
</record>
179236
</odoo>

booking_engine/data/ir_ui_view.xml

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,47 @@
11
<?xml version='1.0' encoding='UTF-8'?>
22
<odoo>
3+
<record id="x_city_tax_form_view" model="ir.ui.view">
4+
<field name="arch" type="xml">
5+
<form>
6+
<field name="x_slot_ids">
7+
<list string="City tax" editable="bottom" multi_edit="1" class="d-flex">
8+
<field name="role_id" string="Room" readonly="True" width="92px"/>
9+
<field name="start_datetime" string="Slot" readonly="True" widget="daterange" options="{'end_date_field': 'end_datetime'}"/>
10+
<field name="x_nights"/>
11+
<field name="x_guests"/>
12+
<field name="x_city_tax"/>
13+
</list>
14+
</field>
15+
<group class="d-flex justify-content-end">
16+
<field name="x_total" class="text-center"/>
17+
</group>
18+
<footer>
19+
<button string="Save" class="btn btn-primary" type="action" name="%(update_city_tax_action)d"/>
20+
<button special="cancel" string="Cancel" class="btn btn-secondary"/>
21+
</footer>
22+
</form>
23+
</field>
24+
<field name="mode">primary</field>
25+
<field name="model">x_city_tax</field>
26+
<field name="name">x_city_tax.form.booking_engine</field>
27+
<field name="priority">200</field>
28+
<field name="type">form</field>
29+
<field name="active" eval="True"/>
30+
</record>
31+
<record id="rental_order_view_inherit" model="ir.ui.view">
32+
<field name="arch" type="xml">
33+
<xpath expr="//button[@name='apply']" position="replace">
34+
<button string="Validate" class="btn btn-primary" type="action" name="%(apply_rental_check_out)d" data-hotkey="q"/>
35+
</xpath>
36+
</field>
37+
<field name="inherit_id" ref="sale_renting.rental_order_wizard_view_form"/>
38+
<field name="mode">extension</field>
39+
<field name="model">rental.order.wizard</field>
40+
<field name="name">rental.order.wizard.form.booking_engine</field>
41+
<field name="priority">200</field>
42+
<field name="type">form</field>
43+
<field name="active" eval="True"/>
44+
</record>
345
<record id="rental_order_view" model="ir.ui.view">
446
<field name="arch" type="xml">
547
<xpath expr="//button[@name='action_open_pickup']" position="attributes">
@@ -9,7 +51,7 @@
951
<attribute name="string">Check Out</attribute>
1052
</xpath>
1153
<xpath expr="//field[@name='is_rental_order']" position="after">
12-
<button string="City Tax" name="%(industry_add_update)d" type="action"/>
54+
<button string="City Tax" type="action" name="%(open_x_city_tax_action)d"/>
1355
</xpath>
1456
<xpath expr="//form[1]/sheet[1]/notebook[1]" position="inside">
1557
<page string="Guests">

0 commit comments

Comments
 (0)