summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjbm-odoo <jbm@odoo.com>2019-08-12 14:49:49 +0000
committerYannick Tivisse <yti@odoo.com>2019-08-21 10:04:54 +0000
commitc230cfa0fe70000f1c1b05a70052d268c821366c (patch)
treeee33bae736ead071db6e4ad1f34f165fae1a2d9d
parent93be40e6eb93f880ef482b2524fa8e238dd0099d (diff)
[ADD] stock_sms: Integration with stock pickings
The user can already send a confirmation email when the Stock Picking is done. It'd be great to communicate the same information by SMS. In addition, the current mailing tool requires a manual action. The idea is to automate the process via a Setting instead. id=1972567 closes odoo/odoo#35662 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
-rw-r--r--addons/delivery/__manifest__.py1
-rw-r--r--addons/delivery/models/stock_picking.py26
-rw-r--r--addons/delivery/views/delivery_view.xml3
-rw-r--r--addons/iap/models/iap.py2
-rw-r--r--addons/stock/__init__.py11
-rw-r--r--addons/stock/__manifest__.py2
-rw-r--r--addons/stock/data/mail_template_data.xml (renamed from addons/delivery/data/mail_template_data.xml)2
-rw-r--r--addons/stock/models/res_company.py11
-rw-r--r--addons/stock/models/res_config_settings.py3
-rw-r--r--addons/stock/models/stock_picking.py17
-rw-r--r--addons/stock/views/res_config_settings_views.xml35
-rw-r--r--addons/stock_sms/__init__.py19
-rw-r--r--addons/stock_sms/__manifest__.py20
-rw-r--r--addons/stock_sms/data/mail_data.xml23
-rw-r--r--addons/stock_sms/data/sms_data.xml13
-rw-r--r--addons/stock_sms/models/__init__.py6
-rw-r--r--addons/stock_sms/models/res_company.py22
-rw-r--r--addons/stock_sms/models/res_config_settings.py14
-rw-r--r--addons/stock_sms/models/stock_picking.py81
-rw-r--r--addons/stock_sms/views/res_config_settings_views.xml22
-rw-r--r--addons/stock_sms/wizard/__init__.py4
-rw-r--r--addons/stock_sms/wizard/confirm_stock_sms.py41
-rw-r--r--addons/stock_sms/wizard/confirm_stock_sms_views.xml31
23 files changed, 377 insertions, 32 deletions
diff --git a/addons/delivery/__manifest__.py b/addons/delivery/__manifest__.py
index 22cb78e9af5..71e51c28708 100644
--- a/addons/delivery/__manifest__.py
+++ b/addons/delivery/__manifest__.py
@@ -23,7 +23,6 @@ invoices from picking, the system is able to add and compute the shipping line.
'views/partner_view.xml',
'views/delivery_portal_template.xml',
'data/delivery_data.xml',
- 'data/mail_template_data.xml',
'views/report_shipping.xml',
'views/report_deliveryslip.xml',
'views/report_package_barcode.xml',
diff --git a/addons/delivery/models/stock_picking.py b/addons/delivery/models/stock_picking.py
index e596c930550..fb31d2da7c4 100644
--- a/addons/delivery/models/stock_picking.py
+++ b/addons/delivery/models/stock_picking.py
@@ -112,13 +112,12 @@ class StockPicking(models.Model):
for picking in self:
picking.weight = sum(move.weight for move in picking.move_lines if move.state != 'cancel')
- def action_done(self):
- res = super(StockPicking, self).action_done()
+ def _send_confirmation_email(self):
for pick in self:
if pick.carrier_id:
if pick.carrier_id.integration_level == 'rate_and_ship' and pick.picking_type_code != 'incoming':
pick.send_to_shipper()
- return res
+ return super(StockPicking, self)._send_confirmation_email()
def _pre_put_in_pack_hook(self, move_line_ids):
res = super(StockPicking, self)._pre_put_in_pack_hook(move_line_ids)
@@ -149,27 +148,6 @@ class StockPicking(models.Model):
),
}
- def action_send_confirmation_email(self):
- self.ensure_one()
- delivery_template_id = self.env.ref('delivery.mail_template_data_delivery_confirmation').id
- compose_form_id = self.env.ref('mail.email_compose_message_wizard_form').id
- ctx = dict(
- default_composition_mode='comment',
- default_res_id=self.id,
- default_model='stock.picking',
- default_use_template=bool(delivery_template_id),
- default_template_id=delivery_template_id,
- custom_layout='mail.mail_notification_light'
- )
- return {
- 'type': 'ir.actions.act_window',
- 'view_mode': 'form',
- 'res_model': 'mail.compose.message',
- 'view_id': compose_form_id,
- 'target': 'new',
- 'context': ctx,
- }
-
def send_to_shipper(self):
self.ensure_one()
res = self.carrier_id.send_shipping(self)[0]
diff --git a/addons/delivery/views/delivery_view.xml b/addons/delivery/views/delivery_view.xml
index f01e918f9bc..8b72083a297 100644
--- a/addons/delivery/views/delivery_view.xml
+++ b/addons/delivery/views/delivery_view.xml
@@ -259,9 +259,6 @@
<xpath expr="/form/header/button[last()]" position="after">
<button name="print_return_label" string="Print Return Label" type="object" attrs="{'invisible':['|', ('is_return_picking', '=', False),('state', '=', 'done')]}"/>
</xpath>
- <xpath expr="//button[@name='do_print_picking']" position="after">
- <button name="action_send_confirmation_email" string="Send Confirmation Email" type="object" attrs="{'invisible':['|', ('state', '!=', 'done'), ('carrier_id', '=', False)]}"/>
- </xpath>
</data>
<xpath expr="//field[@name='partner_id']" position="attributes">
<attribute name="attrs">{'required': ['&amp;', ('delivery_type', '!=', False), ('delivery_type', 'not in', ['fixed', 'base_on_rule'])]}</attribute>
diff --git a/addons/iap/models/iap.py b/addons/iap/models/iap.py
index 608aa52c788..f712d2ae850 100644
--- a/addons/iap/models/iap.py
+++ b/addons/iap/models/iap.py
@@ -167,7 +167,7 @@ class IapAccount(models.Model):
accounts = self.search([
('service_name', '=', service_name),
'|',
- ('company_ids', 'in', self.env.context['allowed_company_ids']),
+ ('company_ids', 'in', self.env.companies.ids),
('company_ids','=',False)],
order='id desc')
if not accounts:
diff --git a/addons/stock/__init__.py b/addons/stock/__init__.py
index 66322ee14f3..f912d4ed8fa 100644
--- a/addons/stock/__init__.py
+++ b/addons/stock/__init__.py
@@ -17,3 +17,14 @@ def pre_init_hook(cr):
('model', 'like', '%stock%'),
('module', '=', 'stock')
]).unlink()
+
+def _assign_default_mail_template_picking_id(cr, registry):
+ env = api.Environment(cr, SUPERUSER_ID, {})
+ company_ids_without_default_mail_template_id = env['res.company'].search([
+ ('stock_mail_confirmation_template_id', '=', False)
+ ])
+ default_mail_template_id = env.ref('stock.mail_template_data_delivery_confirmation', raise_if_not_found=False)
+ if default_mail_template_id:
+ company_ids_without_default_mail_template_id.write({
+ 'stock_mail_confirmation_template_id': default_mail_template_id.id,
+ })
diff --git a/addons/stock/__manifest__.py b/addons/stock/__manifest__.py
index 7df37828b1e..e9c1af7bfa1 100644
--- a/addons/stock/__manifest__.py
+++ b/addons/stock/__manifest__.py
@@ -39,6 +39,7 @@
'report/picking_templates.xml',
'report/product_templates.xml',
'report/product_packaging.xml',
+ 'data/mail_template_data.xml',
'wizard/stock_assign_serial_views.xml',
'wizard/stock_change_product_qty_views.xml',
@@ -86,4 +87,5 @@
'application': True,
'auto_install': False,
'pre_init_hook': 'pre_init_hook',
+ 'post_init_hook': '_assign_default_mail_template_picking_id',
}
diff --git a/addons/delivery/data/mail_template_data.xml b/addons/stock/data/mail_template_data.xml
index e8b6f08ebfc..b1cc5e4d567 100644
--- a/addons/delivery/data/mail_template_data.xml
+++ b/addons/stock/data/mail_template_data.xml
@@ -2,7 +2,7 @@
<odoo><data noupdate="1">
<record id="mail_template_data_delivery_confirmation" model="mail.template">
<field name="name">Delivery: Send by Email</field>
- <field name="model_id" ref="delivery.model_stock_picking"/>
+ <field name="model_id" ref="model_stock_picking"/>
<field name="subject">${object.company_id.name} Delivery Order (Ref ${object.name or 'n/a' })</field>
<field name="partner_to">${object.partner_id.id}</field>
<field name="body_html" type="html">
diff --git a/addons/stock/models/res_company.py b/addons/stock/models/res_company.py
index af6384cbff9..5e5f90e88c2 100644
--- a/addons/stock/models/res_company.py
+++ b/addons/stock/models/res_company.py
@@ -7,9 +7,20 @@ from odoo import api, fields, models, _
class Company(models.Model):
_inherit = "res.company"
+ def _default_confirmation_mail_template(self):
+ try:
+ return self.env.ref('stock.mail_template_data_delivery_confirmation').id
+ except ValueError:
+ return False
+
internal_transit_location_id = fields.Many2one(
'stock.location', 'Internal Transit Location', ondelete="restrict",
help="Technical field used for resupply routes between warehouses that belong to this company")
+ stock_move_email_validation = fields.Boolean("Email Confirmation picking", default=False)
+ stock_mail_confirmation_template_id = fields.Many2one('mail.template', string="Email Template confirmation picking",
+ domain="[('model', '=', 'stock.picking')]",
+ default=_default_confirmation_mail_template,
+ help="Email sent to the customer once the order is done.")
def _create_transit_location(self):
'''Create a transit location with company_id being the given company_id. This is needed
diff --git a/addons/stock/models/res_config_settings.py b/addons/stock/models/res_config_settings.py
index a6675a97c0e..a6c4c9047e6 100644
--- a/addons/stock/models/res_config_settings.py
+++ b/addons/stock/models/res_config_settings.py
@@ -28,6 +28,9 @@ class ResConfigSettings(models.TransientModel):
group_warning_stock = fields.Boolean("Warnings for Stock", implied_group='stock.group_warning_stock')
module_stock_picking_batch = fields.Boolean("Batch Pickings")
module_stock_barcode = fields.Boolean("Barcode Scanner")
+ stock_move_email_validation = fields.Boolean(related='company_id.stock_move_email_validation', readonly=False)
+ stock_mail_confirmation_template_id = fields.Many2one(related='company_id.stock_mail_confirmation_template_id', readonly=False)
+ module_stock_sms = fields.Boolean("SMS Confirmation")
module_delivery = fields.Boolean("Delivery Methods")
module_delivery_dhl = fields.Boolean("DHL USA")
module_delivery_fedex = fields.Boolean("FedEx")
diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py
index d32a82e01ea..dac62ea8491 100644
--- a/addons/stock/models/stock_picking.py
+++ b/addons/stock/models/stock_picking.py
@@ -679,8 +679,14 @@ class Picking(models.Model):
#'qty_done': ops.qty_done})
todo_moves._action_done(cancel_backorder=self.env.context.get('cancel_backorder'))
self.write({'date_done': fields.Datetime.now()})
+ self._send_confirmation_email()
return True
+ def _send_confirmation_email(self):
+ for stock_pick in self.filtered(lambda p: p.company_id.stock_move_email_validation and p.picking_type_id.code == 'outgoing'):
+ delivery_template_id = stock_pick.company_id.stock_mail_confirmation_template_id.id
+ stock_pick.with_context(force_send=True).message_post_with_template(delivery_template_id, email_layout_xmlid='mail.mail_notification_light')
+
@api.depends('state', 'move_lines', 'move_lines.state', 'move_lines.package_level_id', 'move_lines.move_line_ids.package_level_id')
def _compute_move_without_package(self):
for picking in self:
@@ -756,6 +762,9 @@ class Picking(models.Model):
picking.move_lines._do_unreserve()
picking.package_level_ids.filtered(lambda p: not p.move_ids).unlink()
+ def _check_sms_confirmation_popup(self):
+ return False
+
def button_validate(self):
self.ensure_one()
if not self.move_lines and not self.move_line_ids:
@@ -783,6 +792,14 @@ class Picking(models.Model):
if not line.lot_name and not line.lot_id:
raise UserError(_('You need to supply a Lot/Serial number for product %s.') % product.display_name)
+ # Propose to use the sms mechanism the first time a delivery
+ # picking is validated. Whatever the user's decision (use it or not),
+ # the method button_validate is called again (except if it's cancel),
+ # so the checks are made twice in that case, but the flow is not broken
+ sms_confirmation = self._check_sms_confirmation_popup()
+ if sms_confirmation:
+ return sms_confirmation
+
if no_quantities_done:
view = self.env.ref('stock.view_immediate_transfer')
wiz = self.env['stock.immediate.transfer'].create({'pick_ids': [(4, self.id)]})
diff --git a/addons/stock/views/res_config_settings_views.xml b/addons/stock/views/res_config_settings_views.xml
index d90aaefdb71..b783cc58bfb 100644
--- a/addons/stock/views/res_config_settings_views.xml
+++ b/addons/stock/views/res_config_settings_views.xml
@@ -61,8 +61,39 @@
</div>
</div>
<h2>Shipping</h2>
- <div class="row mt16 o_settings_container" title="Shipping connectors allow to compute accurate shipping costs, print shipping labels and request carrier picking at your warehouse to ship to the customer. Apply shipping connector from delivery methods.">
- <div class="col-12 col-lg-6 o_setting_box" id="delivery">
+ <div class="row mt16 o_settings_container">
+ <div class="col-12 col-lg-6 o_setting_box">
+ <div class="o_setting_left_pane">
+ <field name="stock_move_email_validation"/>
+ </div>
+ <div class="o_setting_right_pane">
+ <label for="stock_move_email_validation" string="Email Confirmation"/>
+ <span class="fa fa-lg fa-building-o" title="Values set here are company-specific." groups="base.group_multi_company"/>
+ <div class="text-muted">
+ Send an automatic confirmation email when Delivery Orders are done
+ </div>
+ <div class="row mt16" attrs="{'invisible': [('stock_move_email_validation', '=', False)]}">
+ <label for="stock_mail_confirmation_template_id" string="Email Template" class="col-lg-4 o_light_label"/>
+ <field name="stock_mail_confirmation_template_id" class="oe_inline" attrs="{'required': [('stock_move_email_validation', '=', True)]}" context="{'default_model': 'stock.picking'}"/>
+ </div>
+ </div>
+ </div>
+ <div class="col-12 col-lg-6 o_setting_box">
+ <div class="o_setting_left_pane">
+ <field name="module_stock_sms"/>
+ </div>
+ <div class="o_setting_right_pane">
+ <label for="module_stock_sms"/>
+ <span class="fa fa-lg fa-building-o" title="Values set here are company-specific." groups="base.group_multi_company"/>
+ <div class="text-muted">
+ Send an automatic confirmation SMS Text Message when Delivery Orders are done
+ </div>
+ <div class="content-group">
+ <div id="stock_confirmation_sms"/>
+ </div>
+ </div>
+ </div>
+ <div class="col-12 col-lg-6 o_setting_box" id="delivery" title="Shipping connectors allow to compute accurate shipping costs, print shipping labels and request carrier picking at your warehouse to ship to the customer. Apply shipping connector from delivery methods.">
<div class="o_setting_left_pane">
<field name="module_delivery"/>
</div>
diff --git a/addons/stock_sms/__init__.py b/addons/stock_sms/__init__.py
new file mode 100644
index 00000000000..ef4b88bda90
--- /dev/null
+++ b/addons/stock_sms/__init__.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import models
+from . import wizard
+
+from odoo import api, SUPERUSER_ID
+
+
+def _assign_default_sms_template_picking_id(cr, registry):
+ env = api.Environment(cr, SUPERUSER_ID, {})
+ company_ids_without_default_sms_template_id = env['res.company'].search([
+ ('stock_sms_confirmation_template_id', '=', False)
+ ])
+ default_sms_template_id = env.ref('stock_sms.sms_template_data_stock_delivery', raise_if_not_found=False)
+ if default_sms_template_id:
+ company_ids_without_default_sms_template_id.write({
+ 'stock_sms_confirmation_template_id': default_sms_template_id.id,
+ })
diff --git a/addons/stock_sms/__manifest__.py b/addons/stock_sms/__manifest__.py
new file mode 100644
index 00000000000..5d35cce66da
--- /dev/null
+++ b/addons/stock_sms/__manifest__.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+{
+ 'name': "Stock - SMS",
+ 'summary': 'Send text messages when final stock move',
+ 'description': "Send text messages when final stock move",
+ 'category': 'Hidden',
+ 'version': '1.0',
+ 'depends': ['stock', 'sms'],
+ 'data': [
+ 'data/sms_data.xml',
+ 'data/mail_data.xml',
+ 'views/res_config_settings_views.xml',
+ 'wizard/confirm_stock_sms_views.xml',
+ ],
+ 'application': False,
+ 'auto_install': True,
+ 'post_init_hook': '_assign_default_sms_template_picking_id',
+}
diff --git a/addons/stock_sms/data/mail_data.xml b/addons/stock_sms/data/mail_data.xml
new file mode 100644
index 00000000000..6fe3ced019b
--- /dev/null
+++ b/addons/stock_sms/data/mail_data.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <data>
+
+ <record id="mail_template_no_more_credit_sms" model="mail.template">
+ <field name="name">IAP SMS Confirmation Notification</field>
+ <field name="email_from">iap@odoo.com</field>
+ <field name="subject">IAP SMS Confirmation Notification</field>
+ <field name="model_id" ref="base.model_res_users"/>
+ <field name="partner_to">${object.partner_id.id}</field>
+ <field name="body_html" type="html">
+ <p>Dear ${object.name},</p>
+ <br/>
+ <p>There are no more credits on your IAP SMS account.<br/>
+ You can charge your IAP SMS account from the Settings of the Inventory app or from the General Settings.<br/></p>
+ <br/>
+ <p>Best regards,</p>
+ <p>Odoo S.A.</p>
+ </field>
+ </record>
+
+ </data>
+</odoo>
diff --git a/addons/stock_sms/data/sms_data.xml b/addons/stock_sms/data/sms_data.xml
new file mode 100644
index 00000000000..145a1c68ac3
--- /dev/null
+++ b/addons/stock_sms/data/sms_data.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<odoo>
+ <data noupdate="1">
+ <record id="sms_template_data_stock_delivery" model="sms.template">
+ <field name="name">Delivery: Send by SMS Text Message</field>
+ <field name="model_id" ref="stock.model_stock_picking"/>
+ <field name="body">${object.company_id.name}: We are glad to inform you that your order has been shipped.
+ %if object.carrier_tracking_ref:
+ Your tracking reference is ${object.carrier_tracking_ref}.
+ %endif</field>
+ </record>
+ </data>
+</odoo>
diff --git a/addons/stock_sms/models/__init__.py b/addons/stock_sms/models/__init__.py
new file mode 100644
index 00000000000..81799f3fc79
--- /dev/null
+++ b/addons/stock_sms/models/__init__.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import res_company
+from . import res_config_settings
+from . import stock_picking
diff --git a/addons/stock_sms/models/res_company.py b/addons/stock_sms/models/res_company.py
new file mode 100644
index 00000000000..d7639c8e512
--- /dev/null
+++ b/addons/stock_sms/models/res_company.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+
+class Company(models.Model):
+ _inherit = "res.company"
+
+ def _default_confirmation_sms_picking_template(self):
+ try:
+ return self.env.ref('stock_sms.sms_template_data_stock_delivery').id
+ except ValueError:
+ return False
+
+ stock_move_sms_validation = fields.Boolean("SMS Confirmation", default=True)
+ stock_sms_confirmation_template_id = fields.Many2one(
+ 'sms.template', string="SMS Template",
+ domain="[('model', '=', 'stock.picking')]",
+ default=_default_confirmation_sms_picking_template,
+ help="SMS sent to the customer once the order is done.")
+ has_received_warning_stock_sms = fields.Boolean()
diff --git a/addons/stock_sms/models/res_config_settings.py b/addons/stock_sms/models/res_config_settings.py
new file mode 100644
index 00000000000..12dab58a420
--- /dev/null
+++ b/addons/stock_sms/models/res_config_settings.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+
+class ResConfigSettings(models.TransientModel):
+ _inherit = 'res.config.settings'
+
+ stock_move_sms_validation = fields.Boolean(
+ related='company_id.stock_move_sms_validation',
+ string='SMS Validation with stock move', readonly=False)
+ stock_sms_confirmation_template_id = fields.Many2one(
+ related='company_id.stock_sms_confirmation_template_id', readonly=False)
diff --git a/addons/stock_sms/models/stock_picking.py b/addons/stock_sms/models/stock_picking.py
new file mode 100644
index 00000000000..4813824bf35
--- /dev/null
+++ b/addons/stock_sms/models/stock_picking.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import models, _
+
+import threading
+
+
+class Picking(models.Model):
+ _inherit = 'stock.picking'
+
+ def _sms_get_number_fields(self):
+ """ This method returns the fields to use to find the number to use to
+ send an SMS on a record. """
+ return ['mobile', 'phone']
+
+ def _check_sms_confirmation_popup(self):
+ is_delivery = self.company_id.stock_move_sms_validation \
+ and self.picking_type_id.code == 'outgoing' \
+ and (self.partner_id.mobile or self.partner_id.phone)
+ if is_delivery and not getattr(threading.currentThread(), 'testing', False) \
+ and not self.env.registry.in_test_mode() \
+ and not self.company_id.has_received_warning_stock_sms \
+ and self.company_id.stock_move_sms_validation:
+ view = self.env.ref('stock_sms.view_confirm_stock_sms')
+ wiz = self.env['confirm.stock.sms'].create({'picking_id': self.id})
+ return {
+ 'name': _('SMS'),
+ 'type': 'ir.actions.act_window',
+ 'view_mode': 'form',
+ 'res_model': 'confirm.stock.sms',
+ 'views': [(view.id, 'form')],
+ 'view_id': view.id,
+ 'target': 'new',
+ 'res_id': wiz.id,
+ 'context': self.env.context,
+ }
+ return False
+
+ def _send_confirmation_email(self):
+ super(Picking, self)._send_confirmation_email()
+ if not getattr(threading.currentThread(), 'testing', False) and not self.env.registry.in_test_mode():
+ sms_sent = False
+ pickings = self.filtered(lambda p: p.company_id.stock_move_sms_validation and p.picking_type_id.code == 'outgoing' and (p.partner_id.mobile or p.partner_id.phone))
+
+ for picking in pickings:
+ picking._message_sms_with_template(
+ template=picking.company_id.stock_sms_confirmation_template_id,
+ partner_ids=picking.partner_id.ids,
+ put_in_queue=False
+ )
+ sms_sent = True
+
+ if sms_sent:
+ pickings._check_credit_sms()
+
+ def _check_credit_sms(self):
+ mail_message_ids = self.env['mail.message'].search([
+ ('res_id', 'in', self.ids),
+ ('model', '=', 'stock.picking')]).ids
+ if self.env['ir.config_parameter'].sudo().get_param('stock_sms.already_notified', False):
+ if self.env['sms.sms'].search_count([
+ ('mail_message_id', 'in', mail_message_ids),
+ ('state', '=', 'sent'),
+ ('error_code', '=', False)]):
+ # The SMS is sent, the company has again credits
+ self.env['ir.config_parameter'].sudo().set_param('stock_sms.already_notified', False)
+ else:
+ if self.env['sms.sms'].search_count([
+ ('mail_message_id', 'in', mail_message_ids),
+ ('error_code', '=', 'sms_credit')]):
+ # The SMS is sent, the company has no more credits
+ for admin in self.env.ref('base.group_system').users:
+ mail_template = self.env.ref('stock_sms.mail_template_no_more_credit_sms')
+ email_values = {
+ 'model': 'res.users',
+ 'res_id': admin.id,
+ }
+ mail_template.send_mail(admin.id, email_values=email_values, notif_layout='mail.mail_notification_light')
+
+ self.env['ir.config_parameter'].sudo().set_param('stock_sms.already_notified', True)
diff --git a/addons/stock_sms/views/res_config_settings_views.xml b/addons/stock_sms/views/res_config_settings_views.xml
new file mode 100644
index 00000000000..c389af8310c
--- /dev/null
+++ b/addons/stock_sms/views/res_config_settings_views.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+
+ <record id="res_config_settings_view_form_stock" model="ir.ui.view">
+ <field name="name">res.config.settings.view.form.inherit.delivery.stock</field>
+ <field name="model">res.config.settings</field>
+ <field name="inherit_id" ref="stock.res_config_settings_view_form"/>
+ <field name="arch" type="xml">
+ <xpath expr="//field[@name='module_stock_sms']" position="replace">
+ <field name="stock_move_sms_validation"/>
+ </xpath>
+ <xpath expr="//div[@id='stock_confirmation_sms']" position="replace">
+ <div class="row mt16" attrs="{'invisible': [('stock_move_sms_validation', '=', False)]}">
+ <label for="stock_sms_confirmation_template_id" string="SMS Template" class="col-lg-4 o_light_label"/>
+ <field name="stock_sms_confirmation_template_id" class="oe_inline" attrs="{'required': [('stock_move_sms_validation', '=', True)]}" context="{'default_model': 'stock.picking'}"/>
+ </div>
+ <widget name="iap_buy_more_credits" service_name="sms" attrs="{'invisible': [('stock_move_sms_validation', '=', False)]}"/>
+ </xpath>
+ </field>
+ </record>
+
+</odoo>
diff --git a/addons/stock_sms/wizard/__init__.py b/addons/stock_sms/wizard/__init__.py
new file mode 100644
index 00000000000..67d08c3d237
--- /dev/null
+++ b/addons/stock_sms/wizard/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import confirm_stock_sms
diff --git a/addons/stock_sms/wizard/confirm_stock_sms.py b/addons/stock_sms/wizard/confirm_stock_sms.py
new file mode 100644
index 00000000000..591a6972e74
--- /dev/null
+++ b/addons/stock_sms/wizard/confirm_stock_sms.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models, exceptions
+
+import requests
+
+
+class ConfirmStockSms(models.TransientModel):
+ _name = 'confirm.stock.sms'
+ _description = 'Confirm Stock SMS'
+
+ picking_id = fields.Many2one('stock.picking', required=True)
+ company_id = fields.Many2one('res.company', string='Company', required=True, related='picking_id.company_id')
+ iap_account = fields.Boolean(compute='_compute_iap_account')
+
+ def _compute_iap_account(self):
+ self.iap_account = self.env['iap.account'].get('sms', force_create=False)
+
+ def send_sms(self):
+ self.ensure_one()
+ if not self.company_id.has_received_warning_stock_sms:
+ IAP = self.env['iap.account']
+ if not IAP.get('sms', force_create=False):
+ IAP.get('sms')
+ url = IAP.get_credits_url(service_name='sms', trial=True)
+ try:
+ req = requests.get(url)
+ req.raise_for_status()
+ except (ValueError, requests.exceptions.ConnectionError, requests.exceptions.MissingSchema, requests.exceptions.Timeout, requests.exceptions.HTTPError):
+ raise exceptions.AccessError('The url that this service requested returned an error. Please contact the author of the app. The url it tried to contact was ' + url)
+
+ self.company_id.has_received_warning_stock_sms = True
+ return self.picking_id.button_validate()
+
+ def dont_send_sms(self):
+ self.ensure_one()
+ if not self.company_id.has_received_warning_stock_sms:
+ self.company_id.has_received_warning_stock_sms = True
+ self.company_id.stock_move_sms_validation = False
+ return self.picking_id.button_validate()
diff --git a/addons/stock_sms/wizard/confirm_stock_sms_views.xml b/addons/stock_sms/wizard/confirm_stock_sms_views.xml
new file mode 100644
index 00000000000..bf1c49228bc
--- /dev/null
+++ b/addons/stock_sms/wizard/confirm_stock_sms_views.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <record id="view_confirm_stock_sms" model="ir.ui.view">
+ <field name="name">stock_confirm_sms</field>
+ <field name="model">confirm.stock.sms</field>
+ <field name="arch" type="xml">
+ <form string="SMS">
+ <field name="iap_account" invisible="1"/>
+ You are about to confirm this Delivery Order by SMS Text Message.<br/>
+ This feature can easily be disabled from the Settings of Inventory or by clicking on "Disable SMS".<br/>
+ <br/>
+ <p attrs="{'invisible': [('iap_account', '=', True)]}">
+ When confirming the sending of the SMS Text Message, you will be granted free trial credits.<br/>
+ By buying a pack and using the IAP service, you accept the <a href="https://iap.odoo.com/privacy#sms" target="_blank">Privacy Policy</a> of the service provider
+ and the <a href="https://www.odoo.com/privacy" target="_blank">Odoo Privacy Policy</a>.
+ </p>
+ <group invisible="1">
+ <field name="picking_id" invisible="1"/>
+ <field name="company_id" invisible="1"/>
+ </group>
+ <footer>
+ <button name="send_sms" type="object"
+ string="Confirm" class="oe_highlight"/>
+ <button name="disable_send_sms" type="object"
+ string="Disable SMS" class="oe_highlight"/>
+ <button special="cancel" string="Cancel"/>
+ </footer>
+ </form>
+ </field>
+ </record>
+</odoo>