Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IMP] Hairdresser: Spliting the appointment #199

Open
wants to merge 10 commits into
base: saas-17.4
Choose a base branch
from
6 changes: 6 additions & 0 deletions hair_salon/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
""",
'depends': [
'account_edi_ubl_cii',
"base_automation",
'base_geolocalize',
'hr_hourly_cost',
'knowledge',
Expand All @@ -17,9 +18,14 @@
'sales_team',
'website_appointment',
'theme_orchid',
"web_studio",
],
'data': [
'data/res_config_settings.xml',
'data/ir_model_fields.xml',
'data/ir_ui_view.xml',
'data/ir_actions_server.xml',
'data/base_automation.xml',
'data/project_task_type.xml',
'data/product_template.xml',
'data/product_attribute.xml',
Expand Down
3 changes: 3 additions & 0 deletions hair_salon/data/appointment_type.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
<field name="event_videocall_source" eval="False"/>
<field name="appointment_duration">3.0</field>
<field name="appointment_tz" model="res.users" eval="obj().env.ref('base.user_admin').tz or 'Europe/Brussels'"/>
<field name="x_break" eval="True"/>
<field name="x_break_start_appointment">1.0</field>
<field name="x_break_end_appointment">2.0</field>
<field name="staff_user_ids" eval="[(4, ref('base.user_admin'))]"/>
</record>
<record id="appointment_type_3" model="appointment.type">
Expand Down
24 changes: 24 additions & 0 deletions hair_salon/data/base_automation.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version='1.0' encoding='UTF-8'?>
<odoo>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need a filter_pre_domain? So that it is not run as soon as we touch any calendar.event in the db.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think so, the action is applied on save, and there is a filter domain that restricts it.

<record id="break_booking_automation" model="base.automation">
<field name="name">Delete Main Event</field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="action_server_ids" eval="[(6, 0, [ref('break_booking_server_action')])]"/>
<field name="trigger">on_unlink</field>
<field name="filter_domain">[("appointment_type_id", "!=", False),("x_break_start","!=","False"),("x_break_end","!=","False")]</field>
vava-odoo marked this conversation as resolved.
Show resolved Hide resolved
</record>
<record id="delete_subpart_calendar_event" model="base.automation">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this whole logic wouldn't benefit from adding an on_delete strategy on the new m2o fields that you create (like cascade)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll need more explaination.

<field name="name">Break Appointment</field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="action_server_ids" eval="[(6, 0, [ref('delete_subpart_calendar_event_server_action')])]"/>
<field name="trigger">on_create_or_write</field>
<field name="filter_domain">[("name", "not ilike", "PART 1"), ("name", "not ilike", "PART 2"), ("user_id", "!=", False)]</field>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check should be on other fields (x_parent_id or x_appointment_part_2), not on name

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can we do this since it is for the creation? There is no parent nor appointment before this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the point. Those fields should be empty.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you will have a cascade effect.

</record>
<record id="delete_subpart_main_calendar_event" model="base.automation">
<field name="name">Delete Sub Appointment</field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="action_server_ids" eval="[(6, 0, [ref('delete_subpart_main_calendar_event_server_action')])]"/>
<field name="trigger">on_unlink</field>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the logic with all these unlink. For example, I just tried to unlink the base appointment, none of the "[PART]" ones was archived...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should delete them.

<field name="filter_domain">[("name", "ilike", "PART 1"), ("user_id", "!=", False)]</field>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot find a condition that would work.
This is used to delete subpart, but what condition differs the PART 1 from the PART 2?

</record>
</odoo>
57 changes: 57 additions & 0 deletions hair_salon/data/ir_actions_server.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?xml version='1.0' encoding='UTF-8'?>
<odoo>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you probably need to handle records (and loop), not record

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary.

<record id="break_booking_server_action" model="ir.actions.server">
<field name="code"><![CDATA[
env['calendar.event'].search([('x_parent_id', '=', record.id)]).unlink()
]]></field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="state">code</field>
<field name="name">Execute Code</field>
</record>
<record id="delete_subpart_main_calendar_event_server_action" model="ir.actions.server">
<field name="child_ids" eval="[(6, 0, [ref('break_booking_server_action')])]"/>
<field name="code"><![CDATA[parent_record = env['calendar.event'].browse(record.x_parent_id)
parent_record.x_appointment_part_2.unlink()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

waht about part_1?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can only delete first part tot delete both, otherwise I cannot find a conditions.

parent_record.unlink()]]></field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="state">code</field>
<field name="name">Execute Code</field>
</record>
<record id="delete_subpart_calendar_event_server_action" model="ir.actions.server">
<field name="code"><![CDATA[x_break_start = record.x_break_start
x_break_end = record.x_break_end
appointment_duration = record.duration

start_time = record.start
end_time = record.stop
Comment on lines +21 to +26
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure it's worth to declare intermediate variables

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe not useful. Do you want it to be removed?

event2_vals = {
'name': "[PART 1]" + record.name ,
'start': start_time,
'stop': start_time + datetime.timedelta(hours=x_break_start),
'user_id': record.user_id.id,
'x_parent_id': record.id,
'alarm_ids' : [],
'partner_ids': [record.partner_ids[0].id],
'appointment_type_id':record.appointment_type_id.id,
}
part_1 = env['calendar.event'].create(event2_vals)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you create in batch?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth it for 2 records?


# Third event - From Break End to Original End
event3_vals = {
'name': "[PART 2]" + record.name,
'start': start_time + datetime.timedelta(hours=x_break_end),
'stop': end_time,
'user_id': record.user_id.id,
'partner_ids': [record.partner_ids[0].id],
'x_parent_id': record.id,
'alarm_ids' : [],
'appointment_type_id':record.appointment_type_id.id,
}
part_2 = env['calendar.event'].create(event3_vals)
record.write({'user_id': False, 'show_as': "free",'x_appointment_part_1': part_1.id, 'x_appointment_part_2': part_2.id})
]]></field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="state">code</field>
<field name="name">Execute Code</field>
</record>
</odoo>
57 changes: 57 additions & 0 deletions hair_salon/data/ir_model_fields.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?xml version='1.0' encoding='UTF-8'?>
<odoo>
<record id="x_break_end_appointment_model" model="ir.model.fields">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should maybe make sure that those float are reset to 0 if the user unchecks x_break. What do you think?
For that, I'd move the field to a compute (not readonly and stored), with the python dealing with this only case.

<field name="ttype">float</field>
<field name="field_description">Break End</field>
<field name="model_id" ref="appointment.model_appointment_type"/>
<field name="name">x_break_end_appointment</field>
</record>
<record id="x_break" model="ir.model.fields">
<field name="ttype">boolean</field>
<field name="field_description">Break</field>
<field name="model_id" ref="appointment.model_appointment_type"/>
<field name="help">Insert a free time in your booking.</field>
<field name="name">x_break</field>
</record>
<record id="x_break_start_appointment_model" model="ir.model.fields">
<field name="ttype">float</field>
<field name="field_description">Break Start</field>
<field name="model_id" ref="appointment.model_appointment_type"/>
<field name="name">x_break_start_appointment</field>
</record>
<record id="x_parent_id" model="ir.model.fields">
<field name="ttype">many2one</field>
<field name="field_description">Linked to</field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="name">x_parent_id</field>
<field name="relation">calendar.event</field>
</record>
<record id="x_appointment_part_2" model="ir.model.fields">
<field name="ttype">many2one</field>
<field name="field_description">Part 2</field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="name">x_appointment_part_2</field>
<field name="relation">calendar.event</field>
</record>
<record id="x_appointment_part_1" model="ir.model.fields">
<field name="ttype">many2one</field>
<field name="field_description">Part 1</field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="name">x_appointment_part_1</field>
<field name="relation">calendar.event</field>
</record>
<record id="calendar_x_break_end" model="ir.model.fields">
<field name="ttype">float</field>
<field name="field_description">Break End</field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="name">x_break_end</field>
<field name="related">appointment_type_id.x_break_end_appointment</field>
</record>
<record id="calendar_x_break_start" model="ir.model.fields">
<field name="ttype">float</field>
<field name="field_description">Break Start</field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="name">x_break_start</field>
<field name="related">appointment_type_id.x_break_start_appointment</field>
</record>
</odoo>
70 changes: 70 additions & 0 deletions hair_salon/data/ir_ui_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version='1.0' encoding='UTF-8'?>
<odoo>
<record id="appointment.calendar_event_view_gantt_booking_user" model="ir.ui.view">
<field name="arch" type="xml">
<gantt position="attributes">
<attribute name="default_group_by">user_id</attribute>
</gantt>
</field>
<field name="active" eval="True"/>
<field name="inherit_id" ref="appointment.calendar_event_view_gantt_booking_resource"/>
<field name="model">calendar.event</field>
<field name="name">calendar.event.view.gantt.meeting.user</field>
<field name="type">gantt</field>
</record>
<record id="appointment_type_customization" model="ir.ui.view">
<field name="arch" type="xml">
<xpath expr="//form[1]/sheet[1]/group[1]/group[@name='left_details']/div[1]" position="after">
<field name="x_break" widget="boolean"/>
<field name="x_break_start_appointment" widget="float_time" invisible="not x_break"/>
<field name="x_break_end_appointment" widget="float_time" invisible="not x_break"/>
</xpath>
</field>
<field name="active" eval="True"/>
<field name="inherit_id" ref="appointment.appointment_type_view_form"/>
<field name="mode">extension</field>
<field name="model">appointment.type</field>
<field name="name">appointment.type.form customization</field>
<field name="priority">200</field>
<field name="type">form</field>
</record>
<odoo>
<record id="calendar_event_view_form_gantt_booking_inherit" model="ir.ui.view">
<field name="name">calendar.event.view.form.gantt.booking.inherit</field>
<field name="model">calendar.event</field>
<field name="inherit_id" ref="appointment.calendar_event_view_form_gantt_booking"/>
<field name="active" eval="True"/>
<field name="arch" type="xml">
<xpath expr="//form/sheet/group/group" position="after">
<div class="o_form_group o_inline" invisible="not x_parent_id">
<label for="x_parent_id" string="Linked to:" class="oe_inline me-2"/>
<field name="x_parent_id" options="{'no_create': True}" class="oe_inline"/>
</div>
</xpath>
</field>
</record>
</odoo>
<record id="calendar_event_parent_customization" model="ir.ui.view">
<field name="arch" type="xml">
<xpath expr="//form[1]/sheet[1]/group[1]/group[1]/div[1]" position="after">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Studio exports those very accurate working xpath, but those can easily break due to a change in standard. So we therefore try to shorten this as much as possible (by providing the name of the div, for example)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible for this one but not for all as div are not always unique. Changed what was possible.

<field name="x_break_start" invisible="x_parent_id" widget="float_time"/>
<field name="x_break_end" invisible="x_parent_id" widget="float_time"/>
Comment on lines +50 to +51
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<field name="x_break_start" invisible="x_parent_id" widget="float_time"/>
<field name="x_break_end" invisible="x_parent_id" widget="float_time"/>
<field name="x_break_start" invisible="x_parent_id or not x_break" widget="float_time"/>
<field name="x_break_end" invisible="x_parent_id or not x_break" widget="float_time"/>

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking the view

</xpath>
<xpath expr="//field[@name='location']" position="before">
<field name="x_appointment_part_2" invisible="not x_appointment_part_2"/>
<field name="x_parent_id" invisible="not x_parent_id"/>
</xpath>
<xpath expr="//field[@name='partner_ids']" position="attributes">
<attribute name="force_save">0</attribute>
<attribute name="readonly">False</attribute>
</xpath>
</field>
<field name="active" eval="True"/>
<field name="inherit_id" ref="calendar.view_calendar_event_form"/>
<field name="mode">extension</field>
<field name="model">calendar.event</field>
<field name="name">calendar.event.form customization</field>
<field name="priority">160</field>
<field name="type">form</field>
</record>
</odoo>
Loading