From 79c35c7ba0406846d5799f701f4f2eca4f53bf6f Mon Sep 17 00:00:00 2001 From: Vildan Safin Date: Fri, 13 Mar 2020 09:57:29 +0500 Subject: [PATCH] :bomb: Added child_tree and onload func in js Signed-off-by: Vildan Safin --- saas_apps/__manifest__.py | 2 +- saas_apps/controllers/main.py | 9 +- saas_apps/doc/index.rst | 14 +- saas_apps/models/saas_apps.py | 70 +++++----- saas_apps/static/src/css/calculator.css | 9 +- saas_apps/static/src/js/apps.js | 163 +++++++++++++++--------- saas_apps/views/calculator.xml | 82 ++++++------ saas_apps/views/manage.xml | 6 +- 8 files changed, 197 insertions(+), 158 deletions(-) diff --git a/saas_apps/__manifest__.py b/saas_apps/__manifest__.py index f5f9af7c8..a24d55156 100644 --- a/saas_apps/__manifest__.py +++ b/saas_apps/__manifest__.py @@ -17,7 +17,7 @@ # "price": 9.00, # "currency": "EUR", - "depends": ['website'], + "depends": ['website', 'saas'], "external_dependencies": {"python": [], "bin": []}, "data": [ 'security/ir.model.access.csv', diff --git a/saas_apps/controllers/main.py b/saas_apps/controllers/main.py index a0b9684d8..769e51903 100644 --- a/saas_apps/controllers/main.py +++ b/saas_apps/controllers/main.py @@ -22,11 +22,8 @@ def catch_app_click(self, **kw): @http.route(['/what_dependencies'], type='json', auth='public', website=True) def what_dependencies(self, **kw): - app_name, which_price = kw['args'] - app = http.request.env['saas.line'].search([('name', '=', app_name)]) - month = False - if which_price == 'month': - month = True + app_name = kw['args'][0] + app = http.request.env['saas.line'].search([('module_name', '=', app_name)]) return { - 'dependencies': app.dependencies_info(month, 0) + 'dependencies': app.dependencies_info('root') } diff --git a/saas_apps/doc/index.rst b/saas_apps/doc/index.rst index d8ac8d5a2..b63f051e7 100644 --- a/saas_apps/doc/index.rst +++ b/saas_apps/doc/index.rst @@ -17,17 +17,21 @@ Configuration * `Log in as SUPERUSER `__ * `Activate Developer Mode `__ -* Open menu ``[[ {Menu} ]] >> {Submenu} >> {Subsubmenu}`` -* Click ``[{Button Name}]`` +* Open menu ``[[ Website ]] >> Configuration >> Manage Apps`` +* Click ``[ Refresh ]`` +* Choose modules that you want to make saleable by clicking to ``[ Saleable ]`` Usage ===== {Instruction for daily usage. It should describe how to check that module works. What shall user do and what would user get.} -* Open menu ``[[ {Menu} ]]>> {Submenu} >> {Subsubmenu}`` -* Click ``[{Button Name}]`` -* RESULT: {what user gets, how the modules changes default behaviour} +* Open ``[http://odoo-saas.sh/]`` +* Click ``[{Make new Odoo instance}]`` +* Choose modules that you want to buy by on them +* Choose the using period year/month +* Click ``[Buy now]`` +* RESULT: you will be redirected and logged in to the created build with choosen modules Uninstallation ============== diff --git a/saas_apps/models/saas_apps.py b/saas_apps/models/saas_apps.py index b33b821bd..2ce0722ce 100644 --- a/saas_apps/models/saas_apps.py +++ b/saas_apps/models/saas_apps.py @@ -1,25 +1,20 @@ # Copyright 2020 Vildan Safin # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -from odoo import api, fields, models +from odoo import api, fields, models, modules import logging _logger = logging.getLogger(__name__) class SAASModule(models.Model): - _name = 'saas.module' - _description = 'Model line' + _inherit = 'saas.module' - name = fields.Char(default="default", string="Module Name") month_price = fields.Float(default=0.0, string="Month price") year_price = fields.Float(default=0.0, string="Year price") - icon_path = fields.Char(compute='_compute_path', string="icon path") + icon_path = fields.Char(string="Icon path") saas_modules = fields.Many2one('saas.line', string="Module dependencies") - def _compute_path(self): - self.icon_path = "/saas_apps/static/src/img/%s.png" % self.name - @api.model def create(self, vals): rec = super(SAASModule, self).create(vals) @@ -40,16 +35,11 @@ def add_new_module(self, name): def refresh(self): irmodules = self.env["ir.module.module"].search([]) + ir_module_obj = self.env["ir.module.module"] if len(irmodules) > len(self.search([])): for irmodule in irmodules: if len(self.search([('name', '=', irmodule.name)])) == 0: self.create({'name': irmodule.name}) - - def cost(self, month): - if month: - return self.month_price - else: - return self.year_price class SAASDependence(models.Model): @@ -57,7 +47,8 @@ class SAASDependence(models.Model): _description = 'Module dependencies' # First dependence is root module - name = fields.Char(default="default", string="Module Name") + name = fields.Char(default="default", string="Module technical name") + module_name = fields.Char(default="default", string="Module name") allow_to_sell = fields.Boolean(string="Sellable") dependencies = fields.One2many('saas.module', 'saas_modules', ondelete='cascade', delegate=True) year_price = fields.Float(default=0.0, compute='_compute_year_price', string="Price per year") @@ -65,13 +56,23 @@ class SAASDependence(models.Model): def refresh(self): apps = self.env["saas.module"] + apps.search([]).unlink() + self.search([]).unlink() apps.refresh() - apps = apps.search([]) - if len(apps) > len(self.search([])): - for app in apps: + for app in apps.search([]): + try: if len(self.search([('name', '=', app.name)])) == 0: - new = self.create({'name': app.name}) - new.dependencies += app + new = self.create({ + 'name': app.name, + 'module_name': app.module_name + }) + if len(ir_module_obj.get_module_info(app.name)): + for dep_name in ir_module_obj.get_module_info(app.name)['depends']: + new.dependencies += app.search([('name', '=', dep_name)]) + except: + # import wdb + # wdb.set_trace() + _logger.error("Fuck!") def _compute_year_price(self): for module in self.dependencies: @@ -81,29 +82,26 @@ def _compute_month_price(self): for module in self.dependencies: self.month_price += module.month_price - def dependencies_info(self, for_month, deep): + def dependencies_info(self, root): apps = [] - # Root module - if not deep: - apps.append({ - 'parent': 'root', - 'name': self.name, - 'price': self.dependencies[0].cost(for_month) - }) + childs = [] + for child in self.dependencies - self.dependencies[0]: + childs.append(child.module_name) + apps.append({ + 'parent': root, + 'name': self.module_name, + 'year_price': self.dependencies[0].year_price, + 'month_price': self.dependencies[0].month_price, + 'childs': childs, + 'icon_path': self.dependencies[0].icon_path + }) # Looking to the period for app in self.dependencies - self.dependencies[0]: set = self.search([('name', '=', app.name)]) - leafs = set.dependencies_info(for_month, deep + 1) + leafs = set.dependencies_info(self.name) for leaf in leafs: if not(leaf in apps): apps.append(leaf) - item = { - 'parent': self.name, - 'name': app.name, - 'price': app.cost(for_month) - } - if not(item in apps): - apps.append(item) return apps @api.multi diff --git a/saas_apps/static/src/css/calculator.css b/saas_apps/static/src/css/calculator.css index bef227802..db0137aa9 100644 --- a/saas_apps/static/src/css/calculator.css +++ b/saas_apps/static/src/css/calculator.css @@ -26,7 +26,7 @@ position: fixed; right: 15%; top: 20%; - width: 25%; + width: 20%; z-index: 1; } } @@ -40,4 +40,11 @@ width: 100%; z-index: 1; } + .container{ + margin-left: auto !important; + } +} + +.col-lg-9{ + padding-left: 0px; } \ No newline at end of file diff --git a/saas_apps/static/src/js/apps.js b/saas_apps/static/src/js/apps.js index 120690fef..4d7b795d7 100644 --- a/saas_apps/static/src/js/apps.js +++ b/saas_apps/static/src/js/apps.js @@ -11,7 +11,9 @@ odoo.define('saas_apps.model', function (require){ var per_month = false; /* Also need to add this https://odoo-development.readthedocs.io/en/latest/dev/pos/send-pos-orders-to-server.html#saving-removed-products-of-pos-order-module*/ var choosen = [] - var tree = new Map() + var parent_tree = new Map() + var child_tree = new Map() + var prices = new Map() // Returns element index if element exist in choosen function includes_module(name){ @@ -21,13 +23,23 @@ odoo.define('saas_apps.model', function (require){ return -1; } - // Finding all the links up to the tree, + function Calc_Price(){ + // Calculate general price + price = 0; + var users_price_period = per_month ? 12.5 : 10.0; + for(var i = 0; i < choosen.length; ++i){ + price += choosen[i].price; + } + return price + parseInt($('#users')[0].value, 10)*users_price_period; + } + + // Finding all the links up to the parent_tree, // and push them to delete_list delete_list = []; function leaf_to_root(name){ - if(!delete_list.includes(name)) + if(!delete_list.includes(name) ) delete_list.push(name); - roots = tree.get(name); + roots = parent_tree.get(name); if(roots === undefined) return; if(roots.length > 0){ @@ -38,65 +50,104 @@ odoo.define('saas_apps.model', function (require){ } } - window.onclick=function(e){ - if(window.location.pathname === "/price"){ - if(e.target.className.includes("application")){ - // Looking at choosen period - var price_period = per_month ? 'month' : 'year'; - // Getting choosen module dependecies - session.rpc('/what_dependencies', { - args: [e.target.innerText, price_period] - }).then(function (result) { + leafs = []; + function root_to_leafs(name){ + if(!leafs.includes(name) ) + leafs.push(name); + deps = child_tree.get(name); + if(deps === undefined) + return; + if(deps.length > 0){ + deps.forEach(function(leaf){ + leafs.push(leaf); + root_to_leafs(leaf); + }); + } + } - /* Be carefull with dependecies when changing programm logic, - cause first dependence - is module himself*/ - var i = 0, choosing_new = false; - for(; i < result.dependencies.length; ++i){ - // Add new element to the dependencies tree, cause we'll restablish a path from leaf to the root - // when we'll have to delete one of leafs - if(i > 0){ - modules_parents = tree.get(result.dependencies[i].name); - root_module_name = result.dependencies[i].parent; + window.onload = function() { + var apps = $('.application'), i = 0; + for(; i < apps.length; ++i){ + session.rpc('/what_dependencies', { + args: [apps[i].innerText] + }).then(function (result) { + /* Be carefull with dependecies when changing programm logic, + cause first dependence - is module himself*/ + var i = 0; + for(; i < result.dependencies.length; ++i){ + // Add new element to the dependencies parent_tree, cause we'll restablish a path from leaf to the root + // when we'll have to delete one of leafs + if(i > 0){ + var modules_parents = parent_tree.get(result.dependencies[i].name), + root_module_name = result.dependencies[i].parent, leaf_name = result.dependencies[i].name; - if(modules_parents === undefined){ - tree.set(leaf_name, [root_module_name]); - console.log("INFO:Added new leaf '"+leaf_name+"' with root module '"+root_module_name+"'."); - } - else if(!modules_parents.includes(root_module_name)){ - modules_parents.push(root_module_name); - console.log("INFO:Added new root module '"+root_module_name+"' to leaf '"+leaf_name+"'."); - } - else{ - console.log("WARNING:Root module '"+root_module_name+"' already in tree!"); - } + if(modules_parents === undefined){ + parent_tree.set(leaf_name, [root_module_name]); + console.log("INFO:Added new leaf '"+leaf_name+"' with root module '"+root_module_name+"'."); + }else if(!modules_parents.includes(root_module_name)){ + modules_parents.push(root_module_name); + console.log("INFO:Added new root module '"+root_module_name+"' to leaf '"+leaf_name+"'."); + }else{ + console.log("WARNING:Root module '"+root_module_name+"' already in parent_tree!"); } - leaf_name = result.dependencies[i].name; - if(includes_module(leaf_name) === -1) - { - choosen.push(result.dependencies[i]); - $(".application:contains('"+leaf_name+"')")[0].style.color = "green"; - choosing_new = true; + } + if(result.dependencies[i].childs){ + var root = result.dependencies[i].name, + in_tree_childs = child_tree.get(root); + // Here we get new elements from result.dependencies[i].childs, difference btw + // result.dependencies[i].childs and in_tree_childs. + if(in_tree_childs === undefined){ + child_tree.set(root, result.dependencies[i].childs); + console.log("INFO:Added new root '"+root+"' with childs '"+result.dependencies[i].childs[0]+"...'"); }else{ - if(choosing_new) - continue; - leaf_to_root(leaf_name); - delete_list.forEach(function(module){ - choosen.splice(includes_module(module), 1); - $(".application:contains('"+module+"')")[0].style.color = "black"; + var new_childs = result.dependencies[i].childs.filter(x => !in_tree_childs.includes(x)); + new_childs.forEach(function(child){ + in_tree_childs.push(child); + console.log("INFO:Added new child module '"+child+"' to root '"+root+"'."); }); - delete_list = []; - break; } } - }); + if(prices.get(result.dependencies[i].name) === undefined) + prices.set(result.dependencies[i].name, [result.dependencies[i].month_price, result.dependencies[i].year_price]) + } + }); + } + }; + + window.onclick=function(e){ + if(window.location.pathname === "/price"){ + if(e.target.className.includes("application")){ + var app = e.target.innerText; + if(includes_module(app) === -1) + { + root_to_leafs(app); + leafs.forEach(function(leaf){ + choosen.push({ + 'name': leaf, + 'price': per_month ? prices.get(leaf)[0] : prices.get(leaf)[1] + }); + $(".application:contains('"+leaf+"')")[0].style.color = "green"; + }); + leafs = []; + }else{ + leaf_to_root(app); + delete_list.forEach(function(module){ + var delete_id = includes_module(module); + if(delete_id !== -1){ + choosen.splice(includes_module(module), 1); + $(".application:contains('"+module+"')")[0].style.color = "black"; + } + }); + delete_list = []; + } }else if(e.target.className.includes("nav-link") && (e.target.innerText === "Annually" || e.target.innerText === "Monthly")){ // Check choosen period per_month = e.target.innerText === "Monthly" ? true : false; } price = Calc_Price(); - var period = per_month ? "month" : "year"; - $('#price')[0].innerHTML = '

$'+String(price)+ - ' / '+ period +'

'; + var period = per_month ? "month" : "year"; + $('#price')[0].innerHTML = '

$'+String(price)+ + ' / '+ period +'

'; } } @@ -131,14 +182,4 @@ odoo.define('saas_apps.model', function (require){ // }); // } // }); - - function Calc_Price(){ - // Calculate general price - price = 0; - var users_price_period = per_month ? 12.5 : 10.0; - for(var i = 0; i < choosen.length; ++i){ - price += choosen[i].price; - } - return price + parseInt($('#users')[0].value, 10)*users_price_period; - } }); diff --git a/saas_apps/views/calculator.xml b/saas_apps/views/calculator.xml index 09314fd01..978cbf152 100644 --- a/saas_apps/views/calculator.xml +++ b/saas_apps/views/calculator.xml @@ -6,70 +6,62 @@ Apps
-
+
-

Choose the number of users

-
-
- +
+
+

Choose the number of Users

-
+
+ -
-
+
-
+

Choose your Apps

- - +

-
-
- -
- -
- -
-
-

$15 - / mo

-
    -
  • 20 users included
  • -
  • 10 GB of storage
  • -
  • Priority email support
  • -
  • Help center access
  • -
- + +
+ +
+ +
+
+

$15 + / year

+
    +
  • 20 users included
  • +
  • 10 GB of storage
  • +
  • Priority email support
  • +
  • Help center access
  • +
+ +
+
- +
diff --git a/saas_apps/views/manage.xml b/saas_apps/views/manage.xml index 1dab5b697..1bdb51aa4 100644 --- a/saas_apps/views/manage.xml +++ b/saas_apps/views/manage.xml @@ -14,7 +14,7 @@
-

+

@@ -29,7 +29,7 @@ saas.line - + @@ -40,7 +40,7 @@ saas.line - +