OCA / storage

GNU Affero General Public License v3.0
66 stars 148 forks source link

exisiting attachments migration #310

Open JacooRe opened 7 months ago

JacooRe commented 7 months ago

This is not documented anywhere I looked whatsoever, so whats our options to migrate existing attachments to an s3 object store ?

miikanissi commented 6 months ago

I'm wondering about this myself also. Browsing the fs_attachment code I noticed they have extended the base Odoo force_storage() method on ir.attachment. I tried calling that and it indeed started to migrate all the attachments in the system to our S3.

However it started to migrate every attachment which is not what I was looking for. I was hoping for a way to migrate only selected attachments.

bealdav commented 5 months ago

Thanks to have investigated on this topic @miikanissi . Do you any suggestion to filter attachment: maybe by res_field ? Thanks in advance.

bealdav commented 4 months ago

Maybe can help

import logging

from odoo import models

logger = logging.getLogger(__name__)

def get_domain_for_fs_images():
    return [("image_1920", "!=", False), ("main_image_id", "=", False)]

def get_records(self, limit):
    ids = self.env.context.get("active_ids")
    domain = get_domain_for_fs_images()
    if ids:
        domain.append(("id", "in", ids))
    products = self.env[self._name].search(domain, limit=limit)
    names = [x.display_name for x in products]
    logger.info(f"{len(products)} {self._name} with image moved: {names}")
    return products

class ProductTemplate(models.Model):
    _inherit = "product.template"

    def _move_image_to_fs(self, limit=None):
        """can be called by
        - a server action
        - by shell : should specify limit in this case
        """
        products = get_records(self, limit)
        attach = {
            x.res_id: x
            for x in self.env["ir.attachment"].search(
                [
                    ("res_model", "=", "product.template"),
                    ("res_id", "in", products.ids),
                    ("res_field", "=", "image_1920"),
                ]
            )
        }
        for rec in products:
            self.env["fs.product.image"].create(
                {
                    "product_tmpl_id": rec.id,
                    "specific_image": {
                        "content": rec.image_1920,
                        "filename": attach.get(rec.id) and attach[rec.id].name,
                    },
                }
            )
        # Probably need to move variants images from here but as it depends
        # on product attribute values it's more tricky
<odoo>

    <record id="move_img2fs_product_act_serv" model="ir.actions.server">
        <field name="name">Move Image to File Storage</field>
        <field name="model_id" ref="model_product_template" />
        <field name="binding_model_id" ref="model_product_template" />
        <field name="state">code</field>
        <field name="code">env["product.template"]._move_image_to_fs()</field>
    </record>

</odoo>
CasVissers-360ERP commented 3 months ago

@miikanissi did you find something here? force_storage stores it on S3 but somehow doesn't set fs_filename and updates the store_fname

CasVissers-360ERP commented 3 months ago

In the end I managed to move it correctly (I think), this worked for me but please test carefully (disclaimer):

I think the issue with force_storage is that it times out and is never ran completely.