-
Notifications
You must be signed in to change notification settings - Fork 50
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
Conversation
Help the hair salon to hanlde cases where a task can be break down in 2 parts. The initial appointment is break down in 2 new appointment separeted by a break. task-4100134
The working hours related to the contracts of the employe must be in the same time zone as the appointment. Otherwise this leads to conflict in the timeshifts availible. So now both are on Brussel timezone. task-4100134
In the hair salon the reminder were applied to the child also however we don't want to have reminder on the parent and on the child so the worker does not have too much notifications. Reminder are kept in the parent calendar.event. task-4100134
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @jaeschwa
Thanks for your work on this! It looks promising.
I still have quite a few comments on this. We may need to discuss it further at some point.
Cheers
@@ -0,0 +1,67 @@ | |||
<?xml version='1.0' encoding='UTF-8'?> | |||
<odoo> |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessary.
<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> |
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should delete them.
709b7dc
to
094bda5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still a few comments. I think UX can be improved with a checkbox and maybe add constrains like end>=start
hair_salon/data/ir_ui_view.xml
Outdated
<field name="x_appointment_part_2" string="Part 2" invisible="not x_appointment_part_2"/> | ||
<field name="x_appointment_part_2" invisible="not x_appointment_part_2"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two times? 👀 🤔
Fun fact is that runbot complains about it
<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> |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
<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> | ||
<field name="filter_domain">[("name", "ilike", "PART 1"), ("user_id", "!=", False)]</field> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
There was a problem hiding this comment.
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?
event2_vals = { | ||
'name': "[PART 1]" + record.name , | ||
'start': start_time, | ||
'stop': start_time + datetime.timedelta(hours=x_break_start), | ||
'allday': record.allday, | ||
'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, | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it shorter to duplicate the original one and edit?
For example here the location is not provided
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All theses fields would need to be changed except maybe the user_id and the appointment_type_id.
But we will need to duplicate so +1 line. What would be the advantage of shorter it? Because this is for format but could be written in 1 line.
<field name="trigger">on_unlink</field> | ||
<field name="filter_domain">[("appointment_type_id", "!=", False)]</field> | ||
</record> | ||
<record id="delete_subpart_calendar_event" model="base.automation"> |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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.
094bda5
to
706f499
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're getting close to something
<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() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
waht about part_1?
There was a problem hiding this comment.
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.
<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 |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
'appointment_type_id':record.appointment_type_id.id, | ||
|
||
} | ||
part_1 = env['calendar.event'].create(event2_vals) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
hair_salon/data/ir_ui_view.xml
Outdated
<xpath expr="//field[@name='location']" position="before"> | ||
<field name="x_appointment_part_2" string="Part 2" invisible="not x_appointment_part_2"/> | ||
<field name="x_parent_id" invisible="not x_parent_id"/> | ||
</xpath> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about part_1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have to chose either how to avoid cascade effect?
<field name="x_break_start" invisible="x_parent_id" widget="float_time"/> | ||
<field name="x_break_end" invisible="x_parent_id" widget="float_time"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<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"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking the view
@@ -0,0 +1,57 @@ | |||
<?xml version='1.0' encoding='UTF-8'?> | |||
<odoo> | |||
<record id="x_break_end_appointment_model" model="ir.model.fields"> |
There was a problem hiding this comment.
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="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> |
There was a problem hiding this comment.
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.
706f499
to
8ac3fce
Compare
See #263 |
Purpose: Hairdressers need a more flexible way to manage their appointments. Often, certain services, like a 3-hour brushing, only require their attention for a portion of the time, leaving gaps that could be utilized for other tasks.
Solution: The appointment system has been updated to allow splitting an appointment into two segments with a break in between. This allows the hairdresser to free up time for other tasks while ensuring the customer’s can now book in those break.
Implementation: Added a "break" field in the appointment type setup. Upon booking, the system now creates three appointments: a parent appointment that is sent to the customer and two child appointments representing the active time blocks needed by the hairdresser. These child appointments are linked and adapted to reflect the overall booking, allowing the 1.5-hour gap to be free for other tasks.
task-4100134