File: tour.py

package info (click to toggle)
odoo 18.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 878,716 kB
  • sloc: javascript: 927,937; python: 685,670; xml: 388,524; sh: 1,033; sql: 415; makefile: 26
file content (102 lines) | stat: -rw-r--r-- 3,458 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
from odoo import api, fields, models, Command
import json
import base64


class Tour(models.Model):
    _name = "web_tour.tour"
    _description = "Tours"
    _order = "sequence, name, id"

    name = fields.Char(required=True)
    step_ids = fields.One2many("web_tour.tour.step", "tour_id")
    url = fields.Char(string="Starting URL", default="/odoo")
    sharing_url = fields.Char(compute="_compute_sharing_url", string="Sharing URL")
    rainbow_man_message = fields.Html(default="<b>Good job!</b> You went through all steps of this tour.", translate=True)
    sequence = fields.Integer(default=1000)
    custom = fields.Boolean(string="Custom")
    user_consumed_ids = fields.Many2many("res.users")

    _sql_constraints = [
        ('uniq_name', 'unique(name)', "A tour already exists with this name . Tour's name must be unique!"),
    ]

    @api.depends("name")
    def _compute_sharing_url(self):
        for tour in self:
            tour.sharing_url = f"{tour.get_base_url()}/odoo?tour={tour.name}"

    @api.model
    def consume(self, tourName):
        if self.env.user and self.env.user._is_internal():
            tour_id = self.search([("name", "=", tourName)])
            if tour_id:
                tour_id.sudo().user_consumed_ids = [Command.link(self.env.user.id)]
        return self.get_current_tour()

    @api.model
    def get_current_tour(self):
        if self.env.user and self.env.user.tour_enabled and self.env.user._is_internal():
            tours_to_run = self.search([("custom", "=", False), ("user_consumed_ids", "not in", self.env.user.id)])
            return bool(tours_to_run[:1]) and tours_to_run[:1]._get_tour_json()

    @api.model
    def get_tour_json_by_name(self, tour_name):
        tour_id = self.search([("name", "=", tour_name)])
        return tour_id._get_tour_json()

    def _get_tour_json(self):
        tour_json = self.read(fields={
            "name",
            "url",
            "custom"
        })[0]

        del tour_json["id"]
        tour_json["steps"] = self.step_ids.get_steps_json()
        tour_json["rainbowManMessage"] = self.rainbow_man_message
        return tour_json

    def export_js_file(self):
        js_content = f"""import {{ registry }} from '@web/core/registry';

registry.category("web_tour.tours").add("{self.name}", {{
    url: "{self.url}",
    steps: () => {json.dumps(self.step_ids.get_steps_json(), indent=4)}
}})"""

        attachment_id = self.env["ir.attachment"].create({
            "datas": base64.b64encode(bytes(js_content, 'utf-8')),
            "name": f"{self.name}.js",
            "mimetype": "application/javascript",
            "res_model": "web_tour.tour",
            "res_id": self.id,
        })

        return {
            "type": "ir.actions.act_url",
            "url": f"/web/content/{attachment_id.id}?download=true",
        }


class TourStep(models.Model):
    _name = "web_tour.tour.step"
    _description = "Tour's step"
    _order = "sequence, id"

    trigger = fields.Char(required=True)
    content = fields.Char()
    tour_id = fields.Many2one("web_tour.tour", required=True, ondelete="cascade")
    run = fields.Char()
    sequence = fields.Integer()

    def get_steps_json(self):
        steps = []

        for step in self.read(fields=["trigger", "content", "run"]):
            del step["id"]
            if not step["content"]:
                del step["content"]
            steps.append(step)

        return steps