Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🎉 saas apps #100

Open
wants to merge 60 commits into
base: 12.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
845b109
:tada: first commit
Enigma228322 Feb 22, 2020
b98976d
:bomb: developing process
Enigma228322 Feb 24, 2020
e3b5afa
:bomb: Added Manage Apps view in website configuration
Enigma228322 Feb 28, 2020
29848c6
:bomb: Added 'Refresh' button
Enigma228322 Feb 29, 2020
235ebc2
:bomb: started js low flexing
Enigma228322 Mar 2, 2020
40f02c3
:bomb: Added a little bit calculator logic
Enigma228322 Mar 3, 2020
e8dd2e8
:bomb: Added apps choosing logic
Enigma228322 Mar 3, 2020
58234c9
:bomb: Added price window
Enigma228322 Mar 3, 2020
9e61bae
:bomb: made beautiful price window
Enigma228322 Mar 6, 2020
eb2907d
:bomb: Added tree traversal in js and a little bit in python
Enigma228322 Mar 6, 2020
81e4d1e
:bomb: Added tree
Enigma228322 Mar 7, 2020
79c35c7
:bomb: Added child_tree and onload func in js
Enigma228322 Mar 13, 2020
3154109
:bomb: Made many2many instead one2many btw saas.lines and saas.module…
Enigma228322 Mar 17, 2020
f1a14e0
:bomb: Added pictures and fixied bug with :contains selector, when se…
Enigma228322 Mar 17, 2020
1440f2d
:bomb: shifted block with modules in center
Enigma228322 Mar 17, 2020
b0fa938
:bomb: Made frontend like pushka
Enigma228322 Mar 17, 2020
c47992f
:bomb: Changed allow_to_sell vars changing in overrided write functio…
Enigma228322 Mar 18, 2020
e776229
:bomb: Made access lvl public for not autorized users
Enigma228322 Mar 19, 2020
d1136db
:bomb: Added new template creating and redirecting to new db(Without …
Enigma228322 Mar 27, 2020
29911a7
:bomb: Added auto authorization
Enigma228322 Mar 28, 2020
337085a
:bomb: Added method that collects and sends all modules dependencies …
Enigma228322 Mar 29, 2020
d2aa52b
:bomb: Fixed bug with 'default' named modules
Enigma228322 Mar 29, 2020
787c8e1
:bomb: Now applications only is visible
Enigma228322 Mar 30, 2020
8147ade
:bomb: Added loader and indent corrections
Enigma228322 Mar 31, 2020
9b5d380
:green_heart:
Enigma228322 Mar 31, 2020
cfa5293
:bomb: Made fields editable
Enigma228322 Apr 2, 2020
5c64909
:bomb: temporary
Enigma228322 Apr 6, 2020
80673c3
:bomb: Corrected frontend
Enigma228322 Apr 6, 2020
0e1086b
:green_heart:
Enigma228322 Apr 7, 2020
b038cd6
:bomb: Added saas.line price changing
Enigma228322 Apr 7, 2020
009f9a1
:bomb: Added currency and fixed some bugs
Enigma228322 Apr 8, 2020
ea56bde
:bomb: Added currency linked to the company
Enigma228322 Apr 10, 2020
8419591
:bomb: now template doesn't creates every time, when build creates
Enigma228322 Apr 14, 2020
07f7d44
:bomb: Added 'set_as_base' field in saas_template and this field chec…
Enigma228322 Apr 15, 2020
fde507d
:bomb: added price blink in box, and divided apps price and users price
Enigma228322 Apr 20, 2020
b5ba13d
:bomb: added feature to integrate saas_apps with sign_up form
Enigma228322 Apr 21, 2020
77dfd5a
:bomb: Fixed error with same saas.template.operator name creation
Enigma228322 Apr 21, 2020
32dbf36
:bomb: added base_template record in demo data and docs
Enigma228322 Apr 21, 2020
992e60d
:bomb: Added loader in the begining and choosen_modules saving in loc…
Enigma228322 Apr 22, 2020
1085d17
:bomb: Changed 'Get Started' button, to 'Try trial' and 'Buy now'
Enigma228322 Apr 24, 2020
0a8c338
:bomb: Added packages
Enigma228322 May 2, 2020
1a757b0
:bomb: Added binary icons and corrected saas_apps form view
Enigma228322 May 7, 2020
c571c0c
:bomb: Deleted unnecessary method and added website_sale dependence
Enigma228322 May 8, 2020
e0b6343
:arrow_down::one::two:
Enigma228322 May 9, 2020
540cb72
:bomb: Added users changing buttons at /price page
Enigma228322 May 10, 2020
c2210a4
:bomb: Added apps and packages visibility properties in website settings
Enigma228322 May 11, 2020
838e4a6
:bomb: fixed bug, when price window is absent, values keep calculating
Enigma228322 May 11, 2020
e5fb5d5
:bomb: fixed bug, when saas_apps installs, theres an error with packa…
Enigma228322 May 12, 2020
b1f4710
:bomb: Changed saas_apps settings h2 body
Enigma228322 May 12, 2020
e7ecfcc
:base: Added app alingnment when they're less than 3
Enigma228322 May 12, 2020
e589d21
:book: Added show apps and show packs instr
Enigma228322 May 15, 2020
dd76550
:bomb: Now product.product 'website_published' field related to saas.…
Enigma228322 May 19, 2020
bd57266
:bomb: Changed product.product model relation to product.template
Enigma228322 May 20, 2020
da1e5db
:bomb: Fixed bug. When /price loads button listeners didnt initialize…
Enigma228322 May 20, 2020
47c2974
:bomb: Litle fix to avoid a huge error
Enigma228322 May 25, 2020
da04c05
:bomb: Fixed error, when saas template and package creates in the sam…
Enigma228322 May 26, 2020
0dbe77d
:bomb: Added show 'buy now' button option in settings
Enigma228322 May 28, 2020
37a8121
:bomb: Deleted unnecessary css classes
Enigma228322 Jun 1, 2020
a5b9676
:bomb: 'Try trial' and 'Buy now' are hiding when no application is se…
Enigma228322 Jun 1, 2020
2324ede
:bomb: Fixed bug when currency isn't visible when apps aren't selected
Enigma228322 Jun 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions saas_apps/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.. image:: https://img.shields.io/badge/license-LGPL--3-blue.png
:target: https://www.gnu.org/licenses/lgpl
:alt: License: LGPL-3
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved

===========
Saas Apps
===========

Base module for manage modules in saas.

Module allows to choose modules that users gona use in their db.

Credits
=======

Contributors
------------
* `Vildan Safin <https://www.it-projects.info/team/Enigma228322>`__

Sponsors
--------
* `IT-Projects LLC <https://it-projects.info>`__

Maintainers
-----------
* `IT-Projects LLC <https://it-projects.info>`__

To get a guaranteed support
you are kindly requested to purchase the module
at `odoo apps store <https://apps.odoo.com/apps/modules/12.0/saas_apps/>`__.

Thank you for understanding!

`IT-Projects Team <https://www.it-projects.info/team>`__

Further information
===================

Demo: http://runbot.it-projects.info/demo/odoo-saas-tools/12.0

HTML Description: https://apps.odoo.com/apps/modules/12.0/saas_apps/

Usage instructions: `<doc/index.rst>`_

Changelog: `<doc/changelog.rst>`_

Notifications on updates: `via Atom <https://github.com/it-projects-llc/odoo-saas-tools/commits/12.0/saas_apps.atom>`_, `by Email <https://blogtrottr.com/?subscribe=https://github.com/it-projects-llc/odoo-saas-tools/commits/12.0/saas_apps.atom>`_

Tested on Odoo 12.0 feb7c99f47cae55fff77035fe53975ea4a14d624
2 changes: 2 additions & 0 deletions saas_apps/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import controllers, models
52 changes: 52 additions & 0 deletions saas_apps/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright 2020 Vildan Safin <https://github.com/Enigma228322>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).

{
"name": """SaaS Apps""",
"summary": """Choose your apps""",
"category": "Marketing",
# "live_test_url": "http://apps.it-projects.info/shop/product/DEMO-URL?version=12.0",
"images": ['/images/attention.jpg'],
"version": "12.0.1.0.0",
"application": False,

"author": "IT-Projects LLC, Vildan Safin",
"support": "apps@it-projects.info",
"website": "https://apps.odoo.com/apps/modules/12.0/saas_apps/",
"license": "LGPL-3",
# "price": 9.00,
# "currency": "EUR",

"depends": ['website', 'saas'],
"external_dependencies": {"python": [], "bin": []},
"data": [
'security/ir.model.access.csv',
'views/calculator.xml',
'views/manage.xml',
'views/assets.xml'
],
"demo": [
],
"qweb": [
'views/refresh.xml'
],

"post_load": None,
"pre_init_hook": None,
"post_init_hook": None,
"uninstall_hook": None,

"auto_install": False,
"installable": True,

# "demo_title": "SaaS Apps",
# "demo_addons": [
# ],
# "demo_addons_hidden": [
# ],
# "demo_url": "DEMO-URL",
# "demo_summary": "short",
# "demo_images": [
# "images/MAIN_IMAGE",
# ]
}
2 changes: 2 additions & 0 deletions saas_apps/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import main
97 changes: 97 additions & 0 deletions saas_apps/controllers/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Copyright 2020 Vildan Safin <https://github.com/Enigma228322>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo.http import route, request, Controller
from odoo import http
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
from odoo.addons.saas_public.controllers.saas_public import SaaSPublicController
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
import urllib.parse

DB_TEMPLATE = 'db_template_'

class SaaSAppsController(Controller):


@route('/price', type='http', auth='public', website=True)
def user_page(self, **kw):
apps = http.request.env['saas.line'].sudo()
apps.refresh()
return http.request.render('saas_apps.index', {
'apps': apps.search([('allow_to_sell', '=', True)])
})

@http.route(['/refresh'], type='json', auth='public')
def catch_app_click(self, **kw):
apps = http.request.env['saas.line']
apps.refresh()
return {}

@http.route(['/what_dependencies'], type='json', auth='public')
def what_dependencies(self, **kw):
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
app_tech_name = kw['args'][0]
app = http.request.env['saas.line'].sudo().search([('name', '=', app_tech_name)])
return {
'dependencies': app.dependencies_info('root')
}

class SaaSAppsPublicController(SaaSPublicController):
@http.route(['/create_saas_template'], type='json', auth='public', website=True)
def create_saas_template(self, **kw):
# import wdb
# wdb.set_trace()
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
templates = http.request.env['saas.template']
installing_modules_names = kw['args'][0]
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
saas_template = templates.sudo().create({
'name': 'Template ' + str(len(templates.sudo().search([])) - 1),
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
'template_demo': True,
'public_access': True
})
for name in installing_modules_names:
saas_template.template_module_ids += http.request.env['saas.module'].sudo().search([('name', '=', name)])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using write method is better for such cases

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KolushovAlexandr How it should look like?

installing_modules = []
for name in installing_modules_names:
            installing_modules += request.env['saas.module'].sudo().search([('name', '=', name)])
saas_template.write({'template_module_ids': installing_modules})

saas_operator = http.request.env['saas.operator'].sudo().search([('db_url_template', '=', 'http://{db_name}.{db_id}.127.0.0.1.nip.io')])
saas_template_operator = http.request.env['saas.template.operator'].sudo().create({
'template_id': saas_template.id,
'operator_id': saas_operator.id,
'operator_db_name': DB_TEMPLATE + str(len(http.request.env['saas.template.operator'].sudo().search([])) + 1),
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
})
http.request.env['saas.template.operator'].sudo().preparing_template_next()
return {
'template': saas_template.id,
'template_operator': saas_template_operator.id,
'link': '0',
'Error': '0'
}

@http.route(['/check_saas_template'], type='json', auth='public', website=True)
def is_build_created(self, **kw):
template = http.request.env['saas.template'].sudo().browse(kw['args'][0]['template'])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overloaded construction again

{[{}]} -> {
'template': ...
'template_operator': ...
}

template_operator = http.request.env['saas.template.operator'].sudo().browse(kw['args'][0]['template_operator'])
if len(template) > 0 and template_operator.random_ready_operator_check():
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
kwargs = {}
if template and template.public_access:
template_operator_id = template.operator_ids.random_ready_operator()
build = template_operator_id.create_db(kwargs, with_delay=False)
build_url = build.get_url()
token_obj = request.env['auth_quick_master.token'].sudo().create({
'build': build.id,
'build_login': 'admin',
})
return {
'template': '0',
'template_operator': '0',
'link': urllib.parse.urljoin(build_url, '/auth_quick/check-token?token={}'.format(token_obj.token)),
'Error': '0'
}
else:
return {
'template': '0',
'template_operator': '0',
'link': '0',
'Error': '1'
}
else:
return {
'template': template.id,
'template_operator': template_operator.id,
'link': '0',
'Error': '0'
}
4 changes: 4 additions & 0 deletions saas_apps/doc/changelog.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
`1.0.0`
-------

- **Init version**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍

36 changes: 36 additions & 0 deletions saas_apps/doc/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
===========
Saas Apps
===========

Installation
============

* `Activate longpolling <https://odoo-development.readthedocs.io/en/latest/admin/longpolling.html>`__
*
* `Install <https://odoo-development.readthedocs.io/en/latest/odoo/usage/install-module.html>`__ this module in a usual way

Configuration
=============

* `Log in as SUPERUSER <https://odoo-development.readthedocs.io/en/latest/odoo/usage/login-as-superuser.html>`__
* `Activate Developer Mode <https://odoo-development.readthedocs.io/en/latest/odoo/usage/debug-mode.html>`__
* 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 ``[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
==============

* Open menu ``[[ Apps ]] >> [[SaaS Apps]] >> Uninstall``
Binary file added saas_apps/images/attention.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions saas_apps/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import saas_apps
135 changes: 135 additions & 0 deletions saas_apps/models/saas_apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Copyright 2020 Vildan Safin <https://github.com/Enigma228322>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo import api, fields, models
import logging

_logger = logging.getLogger(__name__)


class SAASModule(models.Model):
_inherit = 'saas.module'

month_price = fields.Float(default=0.0, string="Month price")
year_price = fields.Float(default=0.0, string="Year price")
saas_modules = fields.Many2many('saas.line')

@api.model
def create(self, vals):
rec = super(SAASModule, self).create(vals)
if len(self.saas_modules) > 0:
self.name = self.saas_modules.name
return rec
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved

@api.constrains('month_price', 'year_price')
def _validate_price(self):
if self.month_price < 0 or self.year_price < 0:
raise "Price can't be negative."
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved

def add_new_module(self, name):
self.create({
'name': name
})
return True
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved

def refresh(self):
irmodules = self.env["ir.module.module"].search([])
for irmodule in irmodules:
if len(self.search([('name', '=', irmodule.name)])) == 0:
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
self.create({'name': irmodule.name})


class SAASDependence(models.Model):
_name = 'saas.line'
_description = 'Module dependencies'

# First dependence is root module
name = fields.Char(default="default", string="Module technical name")
module_name = fields.Char(default="default", string="Module name")
icon_path = fields.Char(string="Icon path")
allow_to_sell = fields.Boolean(default=True, string="Sellable")
dependencies = fields.Many2many('saas.module')
year_price = fields.Float(default=0.0, compute='_compute_year_price', string="Price per year")
month_price = fields.Float(default=0.0, compute='_compute_month_price', string="Price per month")

def refresh(self):
apps = self.env["saas.module"]
apps.search([]).unlink()
self.search([]).unlink()
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
apps.refresh()
for app in apps.search([]):
try:
if len(self.search([('name', '=', app.name)])) == 0:
ir_module_obj = self.env["ir.module.module"].get_module_info(app.name)
if len(ir_module_obj):
new = self.create({
'name': app.name,
'module_name': ir_module_obj['name'],
'icon_path': ir_module_obj['icon']
})
new.dependencies += apps.search([('name', '=', app.name)])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Embed it into the record creation

for dep_name in ir_module_obj['depends']:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same

new.dependencies += apps.search([('name', '=', dep_name)])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to query db for each name take a look at how searches domain could be made and make new_dependencies in only one search

else:
new = self.create({'name': app.name})
except:
_logger.error("Fuck!Fuck!Fuck!Fuck!Fuck!Fuck!")
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved

def _compute_year_price(self):
for module in self.dependencies:
self.year_price += module.year_price
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Обнуляем сначала, потом суммируем. Если незаметно от глаз будет 2 раза вызываться _compute_year_price, то ничего хорошего не будет.


def _compute_month_price(self):
for module in self.dependencies:
self.month_price += module.month_price
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Аналогично


def dependencies_info(self, root):
apps = []
childs = []
saas_module = self.dependencies.search([('name', '=', self.name)])
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
for child in self.dependencies - saas_module:
childs.append(child.name)
apps.append({
'parent': root,
'name': self.name,
'year_price': saas_module.year_price,
'month_price': saas_module.month_price,
'childs': childs,
'icon_path': self.icon_path
})
# Looking to the period
for app in self.dependencies - saas_module:
set = self.search([('name', '=', app.name)])
leafs = set.dependencies_info(self.name)
for leaf in leafs:
if not(leaf in apps):
apps.append(leaf)
return apps

@api.multi
def write(self, vals):
res = super(SAASDependence, self).write(vals)
# If value of allow_to_sell changed, other sets allow_to_sell vars should be changed too
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
if "allow_to_sell" in vals:
this_app = self.dependencies.search([('name', '=', self.name)])
for app in self.dependencies - this_app:
self.search([('name', '=', app.name)]).allow_to_sell = vals['allow_to_sell']
return res


class SAASTemplateLine(models.Model):
_inherit = 'saas.template.operator'


@api.multi
def write(self, vals):
if 'state' in vals:
_logger.debug(vals['state'])
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
return super(SAASTemplateLine, self).write(vals)

@api.multi
def random_ready_operator_check(self):
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
ready_operators = self.filtered(lambda r: r.state == 'done')
if len(ready_operators) > 0:
Enigma228322 marked this conversation as resolved.
Show resolved Hide resolved
return True
return False
3 changes: 3 additions & 0 deletions saas_apps/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_saas_line,access_saas_line,model_saas_line,base.group_user,1,1,1,1
access_saas_module,access_saas_module,model_saas_module,base.group_user,1,1,1,1
Comment on lines +1 to +3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если различные манипуляции с saas.module и saas.line будут исключительно в коде, то может быть для пользователей оставим возможность только читать?

Binary file added saas_apps/static/description/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading