class ShopinvaderProduct(models.Model):
    _inherit = "shopinvader.product"

    hierarchical_categories = fields.Serialized(
        compute="_compute_shopinvader_category",
        string="Hierarchical Categories",
    )

    def _category_to_elastic_index_data(self, shopinvader_category):
        categ = shopinvader_category
        parent_names = []
        parent_id = categ.parent_id
        while parent_id:
            parent_names.append(parent_id.name)
            parent_id = parent_id.parent_id
        return {
            "level": categ.level + 1,
            "value": categ.name,
            "ancestors": parent_names,
            "order": categ.sequence,
        }

    def _compute_shopinvader_category(self):
        super(ShopinvaderProduct, self)._compute_shopinvader_category()
        for record in self:
            values = []
            for categ in record.shopinvader_categ_ids:
                values.append(self._category_to_elastic_index_data(categ))
            record.hierarchical_categories = values
class ShopinvaderVariant(models.Model):
    _inherit = 'shopinvader.variant'

    stock_data = fields.Serialized(compute='_compute_stock_data')

    def _get_stock_export_key(self):
        self.ensure_one()
        line = self.env['ir.exports.line'].search([
            ('export_id', '=', self.index_id.exporter_id.id),
            ('name', '=', 'stock_data'),
        ])
        if line.alias:
            return line.alias.split(':')[1]
        else:
            return line.name

    def _prepare_stock_data(self):
        stock_field = self.backend_id.product_stock_field_id.name
        return {'qty': self[stock_field]}

    def _compute_stock_data(self):
        result = defaultdict(dict)
        for backend in self.mapped('backend_id'):
            for wh_key, wh_ids in\
                    backend._get_warehouse_list_for_export().items():
                for loc_record in self.filtered(
                        lambda s: s.backend_id == backend)\
                        .with_context(warehouse=wh_ids):
                    result[loc_record.id][wh_key] =\
                        loc_record._prepare_stock_data()
        for record in self:
            record.stock_data = result[record.id]
Beispiel #3
0
class IrAttachmentStorage(models.Model):
    _name = 'ir.attachment.storage'
    _description = 'Attachment Storage'  # TODO

    name = fields.Char(required=True)
    model = fields.Char(required=True)
    config = fields.Serialized(help="JSON containing all the information")
Beispiel #4
0
class KpiKpiHistory(models.Model):
    _name = "kpi.kpi.history"
    _description = "KPI history"
    _order = "create_date DESC"

    kpi_id = fields.Many2one(
        "kpi.kpi", required=True, ondelete="cascade", readonly=True
    )
    value = fields.Serialized(readonly=True)
    raw_value = fields.Char(compute="_compute_raw_value")
    name = fields.Char(related="kpi_id.name")
    widget = fields.Selection(
        selection=lambda self: self.env["kpi.kpi"]._fields["widget"].selection,
        required=True,
    )

    @api.depends("value")
    def _compute_raw_value(self):
        for record in self:
            record.raw_value = json.dumps(record.value)

    def show_form(self):
        self.ensure_one()
        action = self.env.ref("kpi_dashboard.kpi_kpi_history_act_window")
        result = action.read()[0]
        result.update(
            {
                "res_id": self.id,
                "target": "new",
                "view_mode": "form",
                "views": [(self.env.context.get("form_id"), "form")],
            }
        )
        return result
Beispiel #5
0
class ShopinvaderVariant(models.Model):
    _name = "shopinvader.variant"
    _inherit = ["shopinvader.variant"]

    image_categories = fields.Serialized(compute="_compute_image_categories")

    @api.model
    def _get_category_by_backend(self, record):
        return record.shopinvader_categ_ids.filtered(
            lambda c, v=record: c.record_id == v.categ_id
            and c.index_id.backend_id == v.index_id.backend_id
            and c.images
        )

    @api.multi
    @api.depends(
        "shopinvader_categ_ids",
        "shopinvader_categ_ids.index_id",
        "shopinvader_categ_ids.index_id.backend_id",
        "shopinvader_categ_ids.images",
    )
    def _compute_image_categories(self):
        """
        Compute function for image_categories field.
        This field should contains the value of images field into the first
        category found (with same backend)
        :return:
        """
        for record in self:
            category = self._get_category_by_backend(record)
            record.image_categories = first(category).images or []
Beispiel #6
0
class ShopinvaderVariant(models.Model):
    _inherit = "shopinvader.variant"

    stock_data = fields.Serialized(compute="_compute_stock_data")

    def _get_stock_export_key(self):
        self.ensure_one()
        line = self.env["ir.exports.line"].search([
            ("export_id", "=", self.index_id.exporter_id.id),
            ("name", "=", "stock_data"),
        ])
        if line.alias:
            return line.alias.split(":")[1]
        else:
            return line.name

    def _prepare_stock_data(self):
        stock_field = self.backend_id.product_stock_field_id.name
        return {"qty": self[stock_field]}

    @api.multi
    def _compute_stock_data(self):
        result = defaultdict(dict)
        for backend in self.mapped("backend_id"):
            loc_records = self.filtered(lambda s: s.backend_id == backend)
            for (
                    wh_key,
                    wh_ids,
            ) in backend._get_warehouse_list_for_export().items():

                for loc_record in loc_records.with_context(warehouse=wh_ids):
                    result[loc_record.
                           id][wh_key] = loc_record._prepare_stock_data()
        for record in self:
            record.stock_data = result[record.id]
class ShopinvaderImageMixin(models.AbstractModel):
    _name = 'shopinvader.image.mixin'

    images = fields.Serialized(compute='_compute_image',
                               string='Shopinvader Image')

    def _compute_image(self):
        for record in self:
            record.images = record._get_images_for_record()

    def _get_odoo_image_url(self, base_url):
        return base_url + '/web/image/%s/%s/image' % (self._name, self.id)

    def _get_images_for_record(self):
        self.ensure_one()
        base_url = self.env['ir.config_parameter'].sudo()\
            .get_param('web.base.url')
        image_url = self._get_odoo_image_url(base_url)
        res = {
            'original': {
                'src': image_url,
                'alt': self.name,
            }
        }
        resizes = self.backend_id['%s_resize_ids' %
                                  self._name.replace('.', '_')]
        for resize in resizes:
            res[resize.key] = {
                'src': image_url + '/%sx%s' % (resize.size_x, resize.size_y),
                'alt': self.name,
            }
        return [res]
Beispiel #8
0
class KpiKpiHistory(models.Model):
    _name = 'kpi.kpi.history'
    _description = 'KPI history'
    _order = 'create_date DESC'

    kpi_id = fields.Many2one('kpi.kpi',
                             required=True,
                             ondelete='cascade',
                             readonly=True)
    value = fields.Serialized(readonly=True)
    raw_value = fields.Char(compute='_compute_raw_value')
    name = fields.Char(related='kpi_id.name')
    widget = fields.Selection(
        selection=lambda self: self.env['kpi.kpi']._fields['widget'].selection,
        required=True)

    @api.depends('value')
    def _compute_raw_value(self):
        for record in self:
            record.raw_value = json.dumps(record.value)

    def show_form(self):
        self.ensure_one()
        action = self.env.ref('kpi_dashboard.kpi_kpi_history_act_window')
        result = action.read()[0]
        result.update({
            'res_id': self.id,
            'target': 'new',
            'view_mode': 'form',
            'views': [(self.env.context.get('form_id'), 'form')],
        })
        return result
class SeIndexConfig(models.Model):

    _name = "se.index.config"
    _description = "Elasticsearch index configuration"

    name = fields.Char(required=True)
    body = fields.Serialized(required=True, default="{}")
    # This field is used since no widget exists to edit a serialized field
    # into the web fontend
    body_str = fields.Text(compute="_compute_body_str",
                           inverse="_inverse_body_str")

    @api.multi
    @api.depends("body")
    def _compute_body_str(self):
        for rec in self:
            if rec.body:
                rec.body_str = json.dumps(rec.body)

    @api.multi
    def _inverse_body_str(self):
        for rec in self:
            data = None
            if rec.body_str:
                data = json.loads(rec.body_str)
            rec.body = data
class ShopinvaderVariant(models.Model):
    _inherit = 'shopinvader.variant'

    rating = fields.Serialized(
        compute='_compute_rating',
        string='Rating')

    def _compute_rating(self):
        for record in self:
            reviews = []
            distribution = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0}
            for rating in record.rating_ids:
                if rating.state == 'approved':
                    reviews.append({
                        'nickname': rating.nickname,
                        'name': rating.name,
                        'comment': rating.comment,
                        'rating': rating.rating,
                        'product_code': rating.product_id.default_code,
                        })
                    distribution[rating.rating] += 1
            if reviews:
                count = len(reviews)
                average = sum([c['rating'] for c in reviews]) / count
                record.rating = {
                    'reviews': reviews,
                    'summary': {
                        'average': average,
                        'count': count,
                        'distribution': distribution,
                        }}
            else:
                record.rating = {}
class ShopinvaderVariant(models.Model):
    _inherit = 'shopinvader.variant'

    attributes = fields.Serialized(compute='_compute_attributes',
                                   string='Shopinvader attributes Fields')
    structured_attributes = fields.Serialized(
        compute='_compute_structured_attributes',
        string='Shopinvader attributes Fields')

    def _get_attr_vals(self, attr):
        self.ensure_one()
        if attr.attribute_type == 'select':
            return self[attr.name]['name']
        elif attr.attribute_type == 'multiselect':
            return self[attr.name].mapped('name')
        else:
            return self[attr.name]

    def _compute_attributes(self):
        for record in self:
            attributes = {}
            for group in record.attribute_set_id.attribute_group_ids:
                for attr in group.attribute_ids:
                    # all attr start with "x_" we remove it for the export
                    attributes[attr.name[2:]] = record._get_attr_vals(attr)
            record.attributes = attributes

    def _compute_structured_attributes(self):
        for record in self:
            strc_attr = []
            for group in record.attribute_set_id.attribute_group_ids:
                group_data = {
                    'group_name': group.name,
                    'fields': [],
                }
                for attr in group.attribute_ids:
                    group_data['fields'].append({
                        'name':
                        attr.field_description,
                        'key':
                        attr.name[2:],
                        'value':
                        record._get_attr_vals(attr),
                    })
                strc_attr.append(group_data)
            record.structured_attributes = strc_attr
Beispiel #12
0
class ShopinvaderImageMixin(models.AbstractModel):
    _name = "shopinvader.image.mixin"
    _description = "Shopinvader Image Mixin"
    _image_field = None

    images = fields.Serialized(
        compute="_compute_image", string="Shopinvader Image"
    )

    @api.multi
    def _compute_image(self):
        # Note: this computed field depend on the lang used in the context
        # as the name of the record is used for generating the thumbnail
        for record in self:
            record.images = record._get_image_data_for_record()

    @api.multi
    def _get_image_url_key(self, image_relation):
        # You can inherit this method to change the name of the image of
        # your website. By default we use the name of the product or category
        # linked to the image processed
        # Note the url will be slugify by the get_or_create_thumnail
        self.ensure_one()
        return self.display_name

    @api.multi
    def _get_image_data_for_record(self):
        self.ensure_one()
        res = []
        resizes = self.backend_id[
            "%s_resize_ids" % self._name.replace(".", "_")
        ]
        for image_relation in self[self._image_field]:
            url_key = self._get_image_url_key(image_relation)
            image_data = {}
            for resize in resizes:
                thumbnail = image_relation.image_id.get_or_create_thumbnail(
                    resize.size_x, resize.size_y, url_key=url_key
                )
                image_data[resize.key] = self._prepare_data_resize(
                    thumbnail, image_relation
                )
            res.append(image_data)
        return res

    @api.multi
    def _prepare_data_resize(self, thumbnail, image_relation):
        """
        Prepare data to fill images serialized field
        :param thumbnail: storage.thumbnail recordset
        :param image_relation: product.image.relation recordset
        :return: dict
        """
        self.ensure_one()
        tag = ""
        if image_relation.tag_id:
            tag = image_relation.tag_id.name
        return {"src": thumbnail.url, "alt": self.name, "tag": tag}
class ShopinvaderVariant(models.Model):
    _inherit = "shopinvader.variant"

    attributes = fields.Serialized(
        compute="_compute_attributes", string="Shopinvader attributes Fields"
    )
    structured_attributes = fields.Serialized(
        compute="_compute_structured_attributes",
        string="Shopinvader attributes Fields",
    )

    def _get_attr_vals(self, attr):
        self.ensure_one()
        if attr.attribute_type == "select":
            return self[attr.name]["name"]
        elif attr.attribute_type == "multiselect":
            return self[attr.name].mapped("name")
        else:
            return self[attr.name]

    def _compute_attributes(self):
        for record in self:
            attributes = {}
            for group in record.attribute_set_id.attribute_group_ids:
                for attr in group.attribute_ids:
                    # all attr start with "x_" we remove it for the export
                    attributes[attr.name[2:]] = record._get_attr_vals(attr)
            record.attributes = attributes

    def _compute_structured_attributes(self):
        for record in self:
            strc_attr = []
            for group in record.attribute_set_id.attribute_group_ids:
                group_data = {"group_name": group.name, "fields": []}
                for attr in group.attribute_ids:
                    group_data["fields"].append(
                        {
                            "name": attr.field_description,
                            "key": attr.name[2:],
                            "value": record._get_attr_vals(attr),
                        }
                    )
                strc_attr.append(group_data)
            record.structured_attributes = strc_attr
Beispiel #14
0
class Sparse(models.Model):
    _name = 'test_new_api.sparse'

    data = fields.Serialized()
    boolean = fields.Boolean(sparse='data')
    integer = fields.Integer(sparse='data')
    float = fields.Float(sparse='data')
    char = fields.Char(sparse='data')
    selection = fields.Selection([('one', 'One'), ('two', 'Two')], sparse='data')
    partner = fields.Many2one('res.partner', sparse='data')
Beispiel #15
0
class TestSparse(models.TransientModel):
    _name = 'sparse_fields.test'

    data = fields.Serialized()
    boolean = fields.Boolean(sparse='data')
    integer = fields.Integer(sparse='data')
    float = fields.Float(sparse='data')
    char = fields.Char(sparse='data')
    selection = fields.Selection([('one', 'One'), ('two', 'Two')], sparse='data')
    partner = fields.Many2one('res.partner', sparse='data')
class ShopinvaderProduct(models.Model):
    _inherit = "shopinvader.product"

    hierarchical_categories = fields.Serialized(
        compute="_compute_shopinvader_category",
        string="Hierarchical Categories",
    )

    def _compute_shopinvader_category(self):
        super(ShopinvaderProduct, self)._compute_shopinvader_category()

        def get_full_name(categ):
            result = []
            while categ:
                result.insert(0, categ.name)
                categ = categ.parent_id
            return " > ".join(result)

        for record in self:
            hierarchical_categories = {}
            for categ in record.shopinvader_categ_ids:
                hierarchical_categories["lvl%s" % categ.level] = get_full_name(
                    categ.record_id)
            record.hierarchical_categories = hierarchical_categories

    @api.model
    def _get_facetting_values(self, se_bakend, lang):
        default = [
            "categories.id",
            "Categories.lvl0hierarchical",
            "Categories.lvl1hierarchical",
            "Categories.lvl2hierarchical",
            "main",
            "redirect_url_key",
            "url_key",
            "sku",
            "price.default.value",
        ]
        # Search backend via search engine backend
        invader_backend = self.env["shopinvader.backend"].search(
            [("se_backend_id", "=", se_bakend.id)], limit=1)
        # Product attributes do not have a unique code to reference them.
        # In the index data, the attributes are exported per each lang
        # using the translated name, eg:
        # `variant_attributes.model` for English
        # `variant_attributes.modele` for French
        # which means there's no unique key to search for in the search engine.
        # As a workaround, let's make sure that facet filters use the right one.
        # TODO: in the long term it would be better to have a unique name
        # for every filter/attribute
        # to unify them in indexes and Locomotive settings.
        filters = invader_backend.with_context(lang=lang.code).filter_ids
        filter_facetting_values = [f.display_name for f in filters]
        return default + filter_facetting_values
Beispiel #17
0
class HttpSessionUser(models.TransientModel):
    _name = "http.session.user"
    _description = "User sessions"

    user_id = fields.Many2one("res.users", readonly=True)
    current_session = fields.Boolean(readonly=True)
    session_id = fields.Char(readonly=True)
    session_token = fields.Char(readonly=True)
    ctx = fields.Serialized(readonly=True)
    geoip = fields.Serialized(readonly=True)
    update_time = fields.Datetime(readonly=True)

    @api.multi
    def kill(self):
        self.ensure_one()
        if self.current_session:
            raise UserError(_("Current session cannot be killed"))
        store = http.root.session_store
        session = store.get(self.session_id)
        session.logout(keep_db=True)
        store.save(session)
        self.unlink()
Beispiel #18
0
class StockPicking(models.Model):
    _inherit = "stock.picking"

    tnt_consignment_data = fields.Serialized()
    tnt_consignment_mumber = fields.Char(sparse="tnt_consignment_data")
    tnt_consignment_date = fields.Char(sparse="tnt_consignment_data")
    tnt_consignment_free_circulation = fields.Char(
        sparse="tnt_consignment_data")
    tnt_consignment_sort_split = fields.Char(sparse="tnt_consignment_data")
    tnt_consignment_destination_depot = fields.Char(
        sparse="tnt_consignment_data")
    tnt_consignment_destination_depot_day = fields.Integer(
        sparse="tnt_consignment_data")
    tnt_consignment_cluster_code = fields.Char(sparse="tnt_consignment_data")
    tnt_consignment_origin_depot = fields.Char(sparse="tnt_consignment_data")
    tnt_consignment_product = fields.Char(sparse="tnt_consignment_data")
    tnt_consignment_option = fields.Char(sparse="tnt_consignment_data")
    tnt_consignment_market = fields.Char(sparse="tnt_consignment_data")
    tnt_consignment_transport = fields.Char(sparse="tnt_consignment_data")
    tnt_consignment_transit_depot = fields.Char(sparse="tnt_consignment_data")
    tnt_consignment_xray = fields.Char(sparse="tnt_consignment_data")
    tnt_piece_data = fields.Serialized()
    tnt_piece_barcode = fields.Char(sparse="tnt_piece_data")
Beispiel #19
0
class ShopinvaderBinding(models.AbstractModel):
    _name = "shopinvader.binding"
    _description = "Shopinvader Binding"

    backend_id = fields.Many2one("shopinvader.backend",
                                 string="Backend",
                                 required=True)
    company_id = fields.Many2one(related="backend_id.company_id", store=True)
    external_id = fields.Char(string="External ID")
    sync_date = fields.Datetime(string="Last synchronization date")
    redirect_url_key = fields.Serialized(compute="_compute_redirect_url_key",
                                         string="Redirect Url Keys")

    def _compute_redirect_url_key(self):
        for record in self:
            record.redirect_url_key = record.mapped(
                "redirect_url_url_ids.url_key")
Beispiel #20
0
class TaxjarAccountFiscalPosition(models.Model):

    _name = 'taxjar.account.fiscal.position'
    _inherit = 'taxjar.binding'
    _inherits = {'account.fiscal.position': 'odoo_id'}
    _description = 'TaxJar Nexus Regions'

    _rec_name = 'name'

    odoo_id = fields.Many2one(
        string='Fiscal Position',
        comodel_name='account.fiscal.position',
        required=True,
        ondelete='cascade',
    )
    api_address = fields.Serialized(compute='_compute_api_address', )

    @api.multi
    def _compute_api_address(self):
        for record in self:
            record.api_address = {
                'id': record.external_id or record.id,
                'country': record.country_id.code,
                'state': record.state_ids[0].code,
            }

    @api.model
    def get_by_partner(self, partner, backend=None):

        if backend is None:
            backend = partner.company_id.taxjar_backend_id
        if not backend:
            return

        if partner.property_account_position_id:
            return self.search([
                ('odoo_id', '=', partner.property_account_position_id.id),
                ('backend_id', '=', backend.id),
            ])

        return self.search([
            ('backend_id', '=', backend.id),
            ('country_id', '=', partner.state_id.country_id.id),
            ('state_ids', 'in', partner.state_id.ids),
        ])
class ShopinvaderProduct(models.Model):
    _inherit = "shopinvader.product"

    hierarchical_categories = fields.Serialized(
        compute="_compute_shopinvader_category",
        string="Hierarchical Categories",
    )

    def _compute_shopinvader_category(self):
        super(ShopinvaderProduct, self)._compute_shopinvader_category()

        def get_full_name(categ):
            result = []
            while categ:
                result.insert(0, categ.name)
                categ = categ.parent_id
            return " > ".join(result)

        for record in self:
            hierarchical_categories = {}
            for categ in record.shopinvader_categ_ids:
                hierarchical_categories["lvl%s" % categ.level] = get_full_name(
                    categ.record_id
                )
            record.hierarchical_categories = hierarchical_categories

    @api.model
    def _get_facetting_values(self, se_bakend):
        default = [
            "categories.id",
            "Categories.lvl0hierarchical",
            "Categories.lvl1hierarchical",
            "Categories.lvl2hierarchical",
            "main",
            "redirect_url_key",
            "url_key",
            "sku",
            "price.default.value",
        ]
        invader_backend = self.env["shopinvader.backend"].search(
            [("se_backend_id", "=", se_bakend.id)]
        )
        filters = invader_backend.filter_ids
        filter_facetting_values = [f.display_name for f in filters]
        return default + filter_facetting_values
Beispiel #22
0
class ProductTemplate(models.Model):
    _inherit = 'product.template'

    price_quantity_tiers = fields.Serialized(
        compute='_compute_price_quantity_tiers',
        help='This is a list of minimum quantities where pricing for the'
        ' product changes, along with total costs for each of those'
        ' quantities. It is computed for the current pricelist.',
    )

    @api.multi
    def _compute_price_quantity_tiers(self):
        for record in self:
            current_website = self.env['website'].get_current_website()
            pricelist = current_website.get_current_pricelist()
            pricelist_items = self.env['product.pricelist.item'].search([
                ('pricelist_id', '=', pricelist.id),
                ('product_tmpl_id', '=', record.id),
                '|',
                ('date_start', '<=', fields.Date.today()),
                ('date_start', '=', False),
                '|',
                ('date_end', '>=', fields.Date.today()),
                ('date_end', '=', False),
            ])

            min_quantities = set([])
            for price in pricelist_items:
                min_quantities.add(
                    1 if price.min_quantity < 1 else price.min_quantity)
            if current_website.show_implicit_price_tier:
                min_quantities.add(1)

            list_results = set([])
            for min_qty in min_quantities:
                subtotal = record.with_context(
                    quantity=min_qty, ).website_price
                list_results.add((min_qty, subtotal))

            list_results = sorted(list(list_results))
            # A tier with min qty of 1 should not exist on its own
            if len(list_results) == 1 and list_results[0][0] == 1:
                list_results = []
            record.price_quantity_tiers = json.dumps(list_results)
Beispiel #23
0
class StockPicking(models.Model):
    _inherit = 'stock.picking'

    data = fields.Serialized()
    test_integer = fields.Integer(sparse='data', allow_search=True)
    test_char = fields.Char(sparse='data', allow_search=True)
    test_text = fields.Text(sparse='data', allow_search=True)
    test_float = fields.Float(sparse='data', allow_search=True)
    test_many2one = fields.Many2one('product.product',
                                    sparse='data',
                                    allow_search=True)
    test_many2many = fields.Many2many('product.product',
                                      sparse='data',
                                      allow_search=True)
    test_selection = fields.Selection(selection=[('test1', 'TEST 1'),
                                                 ('test2', 'TEST 2')],
                                      sparse='data',
                                      allow_search=True)
    test_boolean = fields.Boolean(sparse='data', allow_search=True)
Beispiel #24
0
class RancherStack(models.Model):

    _name = 'rancher.stack'
    _inherit = 'rancher.binding'
    _inherits = {'infrastructure.stack': 'odoo_id'}
    _description = 'Rancher Stacks'

    _rec_name = 'name'

    odoo_id = fields.Many2one(
        string='Stack',
        comodel_name='infrastructure.stack',
        required=True,
        ondelete='cascade',
    )
    docker_compose = fields.Text()
    rancher_compose = fields.Text()
    answers = fields.Serialized(default={}, )
    start_on_create = fields.Boolean()
class ShopinvaderImageMixin(models.AbstractModel):
    _name = 'shopinvader.image.mixin'
    _image_field = None

    images = fields.Serialized(compute='_compute_image',
                               string='Shopinvader Image')

    def _compute_image(self):
        # Note: this computed field depend on the lang used in the context
        # as the name of the record is used for generating the thumbnail
        for record in self:
            record.images = record._get_image_data_for_record()

    def _get_image_url_key(self, image_relation):
        # You can inherit this method to change the name of the image of
        # your website. By default we use the name of the product or category
        # linked to the image processed
        # Note the url will be slugify by the get_or_create_thumnail
        return self.display_name

    def _get_image_data_for_record(self):
        self.ensure_one()
        res = []
        resizes = self.backend_id['%s_resize_ids' %
                                  self._name.replace('.', '_')]
        for image_relation in self[self._image_field]:
            url_key = self._get_image_url_key(image_relation)
            image_data = {}
            tag = ''
            if image_relation.tag_id:
                tag = image_relation.tag_id.name
            for resize in resizes:
                thumbnail = image_relation.image_id.get_or_create_thumbnail(
                    resize.size_x, resize.size_y, url_key=url_key)
                image_data[resize.key] = {
                    'src': thumbnail.url,
                    'alt': self.name,
                    'tag': tag,
                }
            res.append(image_data)
        return res
class ShopinvaderVariant(models.Model):
    _inherit = 'shopinvader.variant'

    hierarchical_categories = fields.Serialized(
        compute='_compute_shopinvader_category',
        string='Hierarchical Categories')

    def _compute_shopinvader_category(self):
        super(ShopinvaderVariant, self)._compute_shopinvader_category()

        def get_full_name(categ):
            result = []
            while categ:
                result.insert(0, categ.name)
                categ = categ.parent_id
            return ' > '.join(result)

        for record in self:
            record.hierarchical_categories = {}
            for categ in record.shopinvader_categ_ids:
                record.hierarchical_categories['lvl%s' % categ.level] =\
                    get_full_name(categ.record_id)
class SeIndexConfig(models.Model):

    _name = "se.index.config"
    _description = "Elasticsearch index configuration"

    name = fields.Char(required=True)
    body = fields.Serialized(required=True)
    # This field is used since no widget exists to edit a serialized field
    # into the web fontend
    body_str = fields.Text(compute="_compute_body_str",
                           inverse="_inverse_body_str")

    @api.model
    def create(self, values):
        # For new record creation, the inverse function for `body_str` is
        # called after the record is inserted into database. The field
        # `body` would be empty, and a validation error will pop up as field
        # `body` is required. The solution is to override create function,
        # and initialize field `body` based on field `body_str`.
        if 'body' not in values and 'body_str' in values:
            values['body'] = json.loads(values['body_str'])

        return super(SeIndexConfig, self).create(values)

    @api.multi
    @api.depends("body")
    def _compute_body_str(self):
        for rec in self:
            if rec.body:
                rec.body_str = json.dumps(rec.body)

    @api.multi
    def _inverse_body_str(self):
        for rec in self:
            data = None
            if rec.body_str:
                data = json.loads(rec.body_str)
            rec.body = data
Beispiel #28
0
class SeIndexConfig(models.Model):

    _name = "se.index.config"
    _description = "Elasticsearch index configuration"

    name = fields.Char(required=True)
    doc_type = fields.Char(required=True, default="odoo")
    body = fields.Serialized(required=True)
    # This field is used since no widget exists to edit a serialized field
    # into the web fontend
    body_str = fields.Text(compute="_compute_body_str",
                           inverse="_inverse_body_str")

    @api.multi
    @api.depends("body")
    def _compute_body_str(self):
        for rec in self:
            if rec.body:
                rec.body_str = json.dumps(rec.body)

    @api.multi
    def _inverse_body_str(self):
        for rec in self:
            data = None
            if rec.body_str:
                data = json.loads(rec.body_str)
            rec.body = data

    @api.constrains("doc_type", "body")
    def _check_body(self):
        for rec in self:
            if ("mappings" in rec.body
                    and rec.doc_type not in rec.body["mappings"]):
                raise ValidationError(
                    _("You must specify a mapping into the same doc type "
                      "(%s)") % rec.doc_type)
Beispiel #29
0
class ShopinvaderProduct(models.Model):
    _inherit = "shopinvader.product"

    hierarchical_categories = fields.Serialized(
        compute="_compute_shopinvader_category",
        string="Hierarchical Categories",
    )

    def _compute_shopinvader_category(self):
        super(ShopinvaderProduct, self)._compute_shopinvader_category()

        def get_full_name(categ):
            result = []
            while categ:
                result.insert(0, categ.name)
                categ = categ.parent_id
            return " > ".join(result)

        for record in self:
            record.hierarchical_categories = {}
            for categ in record.shopinvader_categ_ids:
                record.hierarchical_categories[
                    "lvl%s" % categ.level
                ] = get_full_name(categ.record_id)
Beispiel #30
0
class ShopinvaderVariant(models.Model):
    _name = "shopinvader.variant"
    _description = "Shopinvader Variant"
    _inherits = {
        "shopinvader.product": "shopinvader_product_id",
        "product.product": "record_id",
    }

    default_code = fields.Char(related="record_id.default_code", readonly=True)
    shopinvader_product_id = fields.Many2one("shopinvader.product",
                                             required=True,
                                             ondelete="cascade",
                                             index=True)
    record_id = fields.Many2one("product.product",
                                required=True,
                                ondelete="cascade",
                                index=True)
    object_id = fields.Integer(compute="_compute_object_id",
                               store=True,
                               index=True)
    variant_count = fields.Integer(related="product_variant_count")
    variant_attributes = fields.Serialized(
        compute="_compute_variant_attributes", string="Shopinvader Attributes")
    main = fields.Boolean(compute="_compute_main_product")
    redirect_url_key = fields.Serialized(compute="_compute_redirect_url_key",
                                         string="Redirect Url Keys")
    active = fields.Boolean(default=True)
    price = fields.Serialized(compute="_compute_price",
                              string="Shopinvader Price")
    short_name = fields.Char(compute="_compute_names")
    full_name = fields.Char(compute="_compute_names")

    @api.multi
    def _build_seo_title(self):
        """
        Build the SEO product name.
        Call the same function on the related shopinvader product.
        :return: str
        """
        self.ensure_one()
        return self.shopinvader_product_id._build_seo_title()

    def _prepare_variant_name_and_short_name(self):
        self.ensure_one()
        attributes = self.attribute_line_ids.filtered(
            lambda l: len(l.value_ids) > 1).mapped("attribute_id")
        short_name = self.attribute_value_ids._variant_name(attributes)
        full_name = self.shopinvader_display_name
        if short_name:
            full_name += " (%s)" % short_name
        return full_name, short_name

    def _compute_names(self):
        for record in self:
            record.full_name, record.short_name = (
                record._prepare_variant_name_and_short_name())

    def _compute_price(self):
        for record in self:
            record.price = record._get_all_price()

    def _get_all_price(self):
        self.ensure_one()
        res = {}
        pricelist = self.backend_id.pricelist_id
        if pricelist:
            res["default"] = self._get_price(pricelist, None,
                                             self.backend_id.company_id)
        return res

    @api.depends("record_id")
    def _compute_object_id(self):
        for record in self:
            record.object_id = record.record_id.id

    def _compute_redirect_url_key(self):
        for record in self:
            res = []
            for url in record.redirect_url_url_ids:
                res.append(url.url_key)
            record.redirect_url_key = res

    def _compute_variant_attributes(self):
        for record in self:
            variant_attributes = dict()
            for att_value in record.attribute_value_ids:
                sanitized_key = sanitize_attr_name(att_value.attribute_id)
                variant_attributes[sanitized_key] = att_value.name
            record.variant_attributes = variant_attributes

    def _get_price(self, pricelist, fposition, company=None):
        self.ensure_one()
        return self._get_price_per_qty(1, pricelist, fposition, company)

    def _get_price_per_qty(self, qty, pricelist, fposition, company=None):
        product_id = self.record_id
        taxes = product_id.taxes_id.sudo().filtered(
            lambda r: not company or r.company_id == company)
        # get the expeced tax to apply from the fiscal position
        tax_id = fposition.map_tax(taxes, product_id) if fposition else taxes
        tax_id = tax_id and tax_id[0]
        product = product_id.with_context(quantity=qty,
                                          pricelist=pricelist.id,
                                          fiscal_position=fposition)
        final_price, rule_id = pricelist.get_product_price_rule(
            product, qty or 1.0, None)
        tax_included = tax_id.price_include
        account_tax_obj = self.env["account.tax"]
        # fix tax on the price
        value = account_tax_obj._fix_tax_included_price_company(
            final_price, product.taxes_id, tax_id, company)
        res = {
            "value": value,
            "tax_included": tax_included,
            "original_value": value,
            "discount": 0.0,
        }
        if pricelist.discount_policy == "without_discount":
            sol = self.env["sale.order.line"]
            new_list_price, currency_id = sol._get_real_price_currency(
                product, rule_id, qty or 1.0, product.uom_id, pricelist.id)
            # fix tax on the real price
            new_list_price = account_tax_obj._fix_tax_included_price_company(
                new_list_price, product.taxes_id, tax_id, company)
            product_precision = self.env["decimal.precision"].precision_get(
                "Product Price")
            if (float_compare(new_list_price,
                              value,
                              precision_digits=product_precision) == 0):
                # Both prices are equals. Product is wihout discount, avoid
                # divide by 0 exception
                return res
            discount = (new_list_price - value) / new_list_price * 100
            # apply the right precision on discount
            dicount_precision = self.env["decimal.precision"].precision_get(
                "Discount")
            discount = float_round(discount, dicount_precision)
            res.update({
                "original_value": new_list_price,
                "discount": discount
            })
        return res

    def _compute_main_product(self):
        for record in self:
            record.main = record == record.shopinvader_variant_ids[0]