[ADD] pms_satisfaction_survey: send Odoo surveys to PMS guests after checkout#70
Open
DarioLodeiros wants to merge 2 commits into
Open
[ADD] pms_satisfaction_survey: send Odoo surveys to PMS guests after checkout#70DarioLodeiros wants to merge 2 commits into
DarioLodeiros wants to merge 2 commits into
Conversation
Diff CoverageDiff: origin/16.0...HEAD, staged and unstaged changes
Summary
pms_satisfaction_survey/models/pms_folio.pyLines 23-41 23 )
24
25 @api.depends("satisfaction_survey_user_input_id")
26 def _compute_satisfaction_survey_user_input_count(self):
! 27 for folio in self:
! 28 folio.satisfaction_survey_user_input_count = (
29 1 if folio.satisfaction_survey_user_input_id else 0
30 )
31
32 def action_view_satisfaction_survey(self):
! 33 self.ensure_one()
! 34 user_input = self.satisfaction_survey_user_input_id
! 35 if not user_input:
! 36 return False
! 37 return {
38 "type": "ir.actions.act_window",
39 "name": _("Satisfaction Survey"),
40 "res_model": "survey.user_input",
41 "res_id": user_input.id,Lines 46-82 46 def _satisfaction_survey_should_schedule(self):
47 """Return True if the folio is eligible to schedule a satisfaction survey."""
48 self.ensure_one()
49 if self.satisfaction_survey_user_input_id:
! 50 return False
51 prop = self.pms_property_id
52 if not prop or not prop.satisfaction_survey_enabled:
53 return False
! 54 if not prop.satisfaction_survey_id:
! 55 return False
! 56 active_reservations = self.reservation_ids.filtered(
57 lambda r: r.state != "cancel"
58 )
! 59 if not active_reservations:
! 60 return False
! 61 if any(r.state != "done" for r in active_reservations):
! 62 return False
! 63 if not self.email:
! 64 _logger.info(
65 "Folio %s eligible for satisfaction survey but has no email; skipping.",
66 self.display_name,
67 )
! 68 return False
! 69 return True
70
71 def _satisfaction_survey_scheduled_date(self):
72 """Return scheduled_date for the mail.mail per property settings."""
! 73 self.ensure_one()
! 74 prop = self.pms_property_id
! 75 now = fields.Datetime.now()
! 76 if prop.satisfaction_survey_send_moment == "after_checkout":
! 77 return now + timedelta(hours=prop.satisfaction_survey_send_delay_hours)
! 78 return now
79
80 def _try_schedule_satisfaction_survey(self):
81 """Create a survey.user_input for the folio and queue the invitation email.Lines 85-104 85 invite_template = self.env.ref(
86 SURVEY_INVITE_TEMPLATE_XMLID, raise_if_not_found=False
87 )
88 if not invite_template:
! 89 _logger.warning(
90 "Survey invite mail template '%s' not found; cannot send "
91 "satisfaction surveys.",
92 SURVEY_INVITE_TEMPLATE_XMLID,
93 )
! 94 return
95 for folio in self:
96 if not folio._satisfaction_survey_should_schedule():
97 continue
! 98 survey = folio.pms_property_id.satisfaction_survey_id
! 99 scheduled_date = folio._satisfaction_survey_scheduled_date()
! 100 user_input = survey.sudo()._create_answer(
101 partner=folio.partner_id or False,
102 email=folio.email,
103 check_attempts=False,
104 **{"folio_id": folio.id},Lines 102-117 102 email=folio.email,
103 check_attempts=False,
104 **{"folio_id": folio.id},
105 )
! 106 lang = folio.lang or self.env.lang
! 107 invite_template.with_context(lang=lang).send_mail(
108 user_input.id,
109 email_values={"scheduled_date": scheduled_date},
110 force_send=False,
111 )
! 112 folio.satisfaction_survey_user_input_id = user_input
! 113 _logger.info(
114 "Satisfaction survey scheduled for folio %s (user_input %s, "
115 "scheduled_date %s).",
116 folio.display_name,
117 user_input.id,pms_satisfaction_survey/models/pms_property.pyLines 51-60 51 def _check_satisfaction_survey_settings(self):
52 for prop in self:
53 if not prop.satisfaction_survey_enabled:
54 continue
! 55 if not prop.satisfaction_survey_id:
! 56 raise ValidationError(
57 _(
58 "Property %s has satisfaction surveys enabled but no "
59 "survey is selected."
60 )Lines 59-71 59 "survey is selected."
60 )
61 % prop.display_name
62 )
! 63 if (
64 prop.satisfaction_survey_send_moment == "after_checkout"
65 and prop.satisfaction_survey_send_delay_hours <= 0
66 ):
! 67 raise ValidationError(
68 _(
69 "Property %s: delay must be greater than zero when "
70 "sending the survey after checkout."
71 ) |
…checkout Brings native Odoo Surveys into the PMS: - Per-property opt-in with configurable timing (on checkout, or N hours after checkout) and pick of the survey to use. - Ships a default 'Stay Satisfaction Survey' (5 questions, EN + ES) with noupdate=1 so customers can edit it freely. - On the last reservation checkout of a folio, creates a tokenized survey.user_input bound to the folio and queues the standard invitation email via mail.mail.scheduled_date (dispatched by the existing mail.ir_cron_mail_scheduler_action cron). - Strict idempotency: one survey per folio; re-checkout does not duplicate. - Adds folio_id and a stored related pms_property_id to survey.user_input for fast filtering of responses by folio/property; exposes them in the tree/form/search views. - Smart button on the folio form to jump to the linked response.
265d0f5 to
514fcb8
Compare
…of partner_id Folios coming from OTA imports (Booking, Expedia, …) often have no folio.partner_id but do carry the customer email in pms.folio.email (a canonical computed-and-stored field on the folio) and folio.lang. The previous implementation aborted in that case, leaving real-world OTA checkouts without a survey invitation. Switch to folio.email as the source of truth and treat partner_id as optional; lang falls back to env.lang when absent.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
New module
pms_satisfaction_surveythat wires native Odoo Surveys into the PMS so hotels can collect guest feedback automatically after every stay.pms.propertywith configurable timing (on checkout / N hours after) and choice of survey.noupdate=1.survey.user_inputbound to the folio and queues the standard invitation email viamail.mail.scheduled_date(the existingmail.ir_cron_mail_scheduler_actioncron dispatches it).folio_idand a stored relatedpms_property_idtosurvey.user_inputso responses can be filtered by hotel/folio from Surveys → Participations.Verified locally
Installed on
develand ran an end-to-end smoke test inodoo shell:after_checkout+2h, partneren_US:survey.user_inputcreated withfolio_id/pms_property_id,mail.mailqueued withscheduled_date = now + 2h, subject rendered in English.on_checkout, partneres_ES:scheduled_date = now, subject rendered in Spanish (partner.lang propagates viawith_context(lang=...)).user_input.user_inputcreated.Notes
requirements.txtwas regenerated by thesetuptools-odoo-get-requirementspre-commit hook, which collapsed thegit+https://…/roomdoo-smartlocks…entries to bare package names. Plan is to clean this up via rebase after merging this PR to16.0.aldahotels-odoo-16/odoo/custom/src/addons.yaml(handled in a separate change in that repo).Test plan
pms_satisfaction_surveyon a freshpmsDB.survey.user_input+ scheduledmail.mailappear.