diff --git a/addons/mass_mailing_sms/models/sms_sms.py b/addons/mass_mailing_sms/models/sms_sms.py index 504e4417924..298801f3c0e 100644 --- a/addons/mass_mailing_sms/models/sms_sms.py +++ b/addons/mass_mailing_sms/models/sms_sms.py @@ -28,7 +28,7 @@ class SmsSms(models.Model): res[sms.id] = body return res - def _postprocess_iap_sent_sms(self, iap_results, failure_reason=None, delete_all=False): + def _postprocess_iap_sent_sms(self, iap_results, failure_reason=None, unlink_failed=False, unlink_sent=True): all_sms_ids = [item['res_id'] for item in iap_results] if any(sms.mailing_id for sms in self.env['sms.sms'].sudo().browse(all_sms_ids)): for state in self.IAP_TO_SMS_STATE.keys(): @@ -40,4 +40,7 @@ class SmsSms(models.Model): traces.set_sent() elif traces: traces.set_failed(failure_type=self.IAP_TO_SMS_STATE[state]) - return super(SmsSms, self)._postprocess_iap_sent_sms(iap_results, failure_reason=failure_reason, delete_all=delete_all) + return super(SmsSms, self)._postprocess_iap_sent_sms( + iap_results, failure_reason=failure_reason, + unlink_failed=unlink_failed, unlink_sent=unlink_sent + ) diff --git a/addons/sms/models/sms_sms.py b/addons/sms/models/sms_sms.py index e9b4c900838..e0907d93d4a 100644 --- a/addons/sms/models/sms_sms.py +++ b/addons/sms/models/sms_sms.py @@ -45,23 +45,57 @@ class SmsSms(models.Model): ('sms_optout', 'Opted Out'), ], copy=False) - def send(self, delete_all=False, auto_commit=False, raise_exception=False): + def action_set_canceled(self): + self.state = 'canceled' + notifications = self.env['mail.notification'].sudo().search([ + ('sms_id', 'in', self.ids), + # sent is sent -> cannot reset + ('notification_status', 'not in', ['canceled', 'sent']), + ]) + if notifications: + notifications.write({'notification_status': 'canceled'}) + if not self._context.get('sms_skip_msg_notification', False): + notifications.mail_message_id._notify_message_notification_update() + + def action_set_error(self, failure_type): + self.state = 'error' + self.failure_type = failure_type + notifications = self.env['mail.notification'].sudo().search([ + ('sms_id', 'in', self.ids), + # sent can be set to error due to IAP feedback + ('notification_status', '!=', 'exception'), + ]) + if notifications: + notifications.write({'notification_status': 'exception', 'failure_type': failure_type}) + if not self._context.get('sms_skip_msg_notification', False): + notifications.mail_message_id._notify_message_notification_update() + + def action_set_outgoing(self): + self.state = 'outgoing' + notifications = self.env['mail.notification'].sudo().search([ + ('sms_id', 'in', self.ids), + # sent is sent -> cannot reset + ('notification_status', 'not in', ['ready', 'sent']), + ]) + if notifications: + notifications.write({'notification_status': 'ready', 'failure_type': False}) + if not self._context.get('sms_skip_msg_notification', False): + notifications.mail_message_id._notify_message_notification_update() + + def send(self, unlink_failed=False, unlink_sent=True, auto_commit=False, raise_exception=False): """ Main API method to send SMS. - :param delete_all: delete all SMS (sent or not); otherwise delete only - sent SMS; + :param unlink_failed: unlink failed SMS after IAP feedback; + :param unlink_sent: unlink sent SMS after IAP feedback; :param auto_commit: commit after each batch of SMS; :param raise_exception: raise if there is an issue contacting IAP; """ for batch_ids in self._split_batch(): - self.browse(batch_ids)._send(delete_all=delete_all, raise_exception=raise_exception) + self.browse(batch_ids)._send(unlink_failed=unlink_failed, unlink_sent=unlink_sent, raise_exception=raise_exception) # auto-commit if asked except in testing mode if auto_commit is True and not getattr(threading.currentThread(), 'testing', False): self._cr.commit() - def set_outgoing(self): - self.state = 'outgoing' - def resend_failed(self): sms_to_send = self.filtered(lambda sms: sms.state == 'error') notification_title = _('Warning') @@ -88,9 +122,6 @@ class SmsSms(models.Model): } } - def cancel(self): - self.state = 'canceled' - @api.model def _process_queue(self, ids=None): """ Send immediately queued messages, committing after each message is sent. @@ -112,7 +143,7 @@ class SmsSms(models.Model): try: # auto-commit except in testing mode auto_commit = not getattr(threading.currentThread(), 'testing', False) - res = self.browse(ids).send(delete_all=False, auto_commit=auto_commit, raise_exception=False) + res = self.browse(ids).send(unlink_failed=False, unlink_sent=True, auto_commit=auto_commit, raise_exception=False) except Exception: _logger.exception("Failed processing SMS queue") return res @@ -122,7 +153,7 @@ class SmsSms(models.Model): for sms_batch in tools.split_every(batch_size, self.ids): yield sms_batch - def _send(self, delete_all=False, raise_exception=False): + def _send(self, unlink_failed=False, unlink_sent=True, raise_exception=False): """ This method tries to send SMS after checking the number (presence and formatting). """ iap_data = [{ @@ -137,25 +168,33 @@ class SmsSms(models.Model): _logger.info('Sent batch %s SMS: %s: failed with exception %s', len(self.ids), self.ids, e) if raise_exception: raise - self._postprocess_iap_sent_sms([{'res_id': sms.id, 'state': 'server_error'} for sms in self], delete_all=delete_all) + self._postprocess_iap_sent_sms( + [{'res_id': sms.id, 'state': 'server_error'} for sms in self], + unlink_failed=unlink_failed, unlink_sent=unlink_sent) else: _logger.info('Send batch %s SMS: %s: gave %s', len(self.ids), self.ids, iap_results) - self._postprocess_iap_sent_sms(iap_results, delete_all=delete_all) + self._postprocess_iap_sent_sms(iap_results, unlink_failed=unlink_failed, unlink_sent=unlink_sent) - def _postprocess_iap_sent_sms(self, iap_results, failure_reason=None, delete_all=False): - if delete_all: - todelete_sms_ids = [item['res_id'] for item in iap_results] - else: - todelete_sms_ids = [item['res_id'] for item in iap_results if item['state'] == 'success'] + def _postprocess_iap_sent_sms(self, iap_results, failure_reason=None, unlink_failed=False, unlink_sent=True): + todelete_sms_ids = [] + if unlink_failed: + todelete_sms_ids += [item['res_id'] for item in iap_results if item['state'] != 'success'] + if unlink_sent: + todelete_sms_ids += [item['res_id'] for item in iap_results if item['state'] == 'success'] for state in self.IAP_TO_SMS_STATE.keys(): sms_ids = [item['res_id'] for item in iap_results if item['state'] == state] if sms_ids: - if state != 'success' and not delete_all: + if state != 'success' and not unlink_failed: self.env['sms.sms'].sudo().browse(sms_ids).write({ 'state': 'error', 'failure_type': self.IAP_TO_SMS_STATE[state], }) + if state == 'success' and not unlink_sent: + self.env['sms.sms'].sudo().browse(sms_ids).write({ + 'state': 'sent', + 'failure_type': False, + }) notifications = self.env['mail.notification'].sudo().search([ ('notification_type', '=', 'sms'), ('sms_id', 'in', sms_ids), diff --git a/addons/sms/tests/common.py b/addons/sms/tests/common.py index b454796e81c..ed1351ebae5 100644 --- a/addons/sms/tests/common.py +++ b/addons/sms/tests/common.py @@ -21,7 +21,7 @@ class MockSMS(common.BaseCase): def mockSMSGateway(self, sms_allow_unlink=False, sim_error=None, nbr_t_error=None): self._clear_sms_sent() sms_create_origin = SmsSms.create - sms_unlink_origin = SmsSms.unlink + sms_send_origin = SmsSms._send def _contact_iap(local_endpoint, params): # mock single sms sending @@ -60,18 +60,17 @@ class MockSMS(common.BaseCase): self._new_sms += res.sudo() return res - def _sms_sms_unlink(records, *args, **kwargs): + def _sms_sms_send(records, unlink_failed=False, unlink_sent=True, raise_exception=False): if sms_allow_unlink: - return sms_unlink_origin(records, *args, **kwargs) - # hack: instead of unlink, update state to sent for tests + return sms_send_origin(records, unlink_failed=unlink_failed, unlink_sent=unlink_sent, raise_exception=raise_exception) else: - records.filtered(lambda sms: sms.id in self._new_sms.ids).state = 'sent' + return sms_send_origin(records, unlink_failed=False, unlink_sent=False, raise_exception=raise_exception) return True try: with patch.object(SmsApi, '_contact_iap', side_effect=_contact_iap), \ patch.object(SmsSms, 'create', autospec=True, wraps=SmsSms, side_effect=_sms_sms_create), \ - patch.object(SmsSms, 'unlink', autospec=True, wraps=SmsSms, side_effect=_sms_sms_unlink): + patch.object(SmsSms, '_send', autospec=True, wraps=SmsSms, side_effect=_sms_sms_send): yield finally: pass diff --git a/addons/sms/views/sms_sms_views.xml b/addons/sms/views/sms_sms_views.xml index 19f4811d15f..4229eb3896e 100644 --- a/addons/sms/views/sms_sms_views.xml +++ b/addons/sms/views/sms_sms_views.xml @@ -7,8 +7,8 @@