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

[13.0][IMP] Attachment Integration #9

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions dms/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@

from . import res_company
from . import res_config_settings
from . import ir_attachment
8 changes: 8 additions & 0 deletions dms/models/directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ class DmsDirectory(models.Model):
""",
)

record_ref = fields.Reference(
string="Record Referenced", selection="_select_reference", readonly=True,
)

@api.depends("name", "complete_name")
def _compute_display_name(self):
if not self.env.context.get("directory_short_name", False):
Expand Down Expand Up @@ -557,3 +561,7 @@ def unlink(self):
DmsDirectory, self.sudo().search([("id", "child_of", self.ids)])
).unlink()
return super().unlink()

def _select_reference(self):
model_ids = self.env["ir.model"].search([])
return [(r["model"], r["name"]) for r in model_ids] + [("", "")]
69 changes: 67 additions & 2 deletions dms/models/dms_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,18 @@ class File(models.Model):
attachment=True, string="Content File", prefetch=False, invisible=True
)

attachment_id = fields.Many2one(
comodel_name="ir.attachment",
string="Attachment File",
prefetch=False,
invisible=True,
ondelete="cascade",
)

record_ref = fields.Reference(
string="Record Referenced", selection="_select_reference", readonly=True,
)

# ----------------------------------------------------------
# Helper
# ----------------------------------------------------------
Expand All @@ -172,6 +184,8 @@ def _update_content_vals(self, vals, binary):
)
if self.storage_id.save_type == "file":
new_vals["content_file"] = self.content
elif self.storage_id.save_type == "attachment":
new_vals["attachment_id"] = self.content
Comment on lines 185 to +188
Copy link
Member

Choose a reason for hiding this comment

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

It's very strange because in V12 don't work #24 (comment).
Solved (V12) with this changes:

Suggested change
if self.storage_id.save_type == "file":
new_vals["content_file"] = self.content
elif self.storage_id.save_type == "attachment":
new_vals["attachment_id"] = self.content
if self.storage_id.save_type in ["file", "attachment"]:
new_vals["content_file"] = self.content

elif self.storage_id.save_type == "database":
new_vals["content_binary"] = self.content and binary
return new_vals
Expand Down Expand Up @@ -356,15 +370,18 @@ def _compute_mimetype(self):
mimetype = guess_mimetype(binary, default="application/octet-stream")
record.res_mimetype = mimetype

@api.depends("content_binary", "content_file")
@api.depends("content_binary", "content_file", "attachment_id")
def _compute_content(self):
bin_size = self.env.context.get("bin_size", False)
for record in self:
if record.content_file:
context = {"human_size": True} if bin_size else {"base64": True}
record.content = record.with_context(context).content_file
else:
elif record.content_binary:
record.content = base64.b64encode(record.content_binary)
else:
context = {"human_size": True} if bin_size else {"base64": True}
record.content = record.with_context(context).attachment_id.datas

@api.depends("content_binary", "content_file")
def _compute_save_type(self):
Expand Down Expand Up @@ -560,6 +577,43 @@ def _inverse_content(self):
for vals, ids in updates.items():
self.browse(ids).write(dict(vals))

def _create_model_attachment(self, vals):

if "default_directory_id" in self._context:
default_directory_id = (
self.env["dms.directory"]
.with_user(SUPERUSER_ID)
.browse(self._context["default_directory_id"])
)

vals["directory_id"] = default_directory_id.id

directory_id = (
self.env["dms.directory"]
.with_user(SUPERUSER_ID)
.browse(vals["directory_id"])
)

if directory_id and directory_id.record_ref:

if directory_id.record_ref:
model_name = directory_id.record_ref._name
model_id = directory_id.record_ref.id

attachment_id = self.env["ir.attachment"].create(
{
"name": vals["name"],
"datas": vals["content"],
"res_model": model_name,
"res_id": model_id,
"dms_file": True,
}
)

vals["attachment_id"] = attachment_id.id
vals["record_ref"] = "{},{}".format(model_name, model_id)
del vals["content"]

def copy(self, default=None):
self.ensure_one()
default = dict(default or [])
Expand All @@ -586,6 +640,13 @@ def unlink(self):
# will be deleted
return super(File, self.sudo()).unlink()

@api.model
def create(self, vals):
if "record_ref" not in vals:
self._create_model_attachment(vals)

return super(File, self).create(vals)

# ----------------------------------------------------------
# Locking fields and functions
# ----------------------------------------------------------
Expand Down Expand Up @@ -634,3 +695,7 @@ def _compute_locked(self):
)
else:
record.update({"is_locked": False, "is_lock_editor": False})

def _select_reference(self):
model_ids = self.env["ir.model"].search([])
return [(r["model"], r["name"]) for r in model_ids] + [("", "")]
85 changes: 85 additions & 0 deletions dms/models/ir_attachment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import re

from odoo import api, models


class IrAttachment(models.Model):

_inherit = "ir.attachment"

def _dms_file_name(self, directory_id, file_name):
count = 1
for file in directory_id.file_ids:

dms_file_name = re.sub(r" \([0-9]*\)", "", file.name)
if dms_file_name == file_name:
count += 1

file, ext = re.split(r"\.", file_name)
return file + " ({}).".format(count) + ext if count > 1 else file_name

def _create_record_dir(self, storage_id, attachment_id):
dms_field = self.env["ir.module.module"].search([("name", "=", "dms_field")])

directory_fields = {
"name": attachment_id.res_name.replace("/", "-"),
"is_root_directory": True,
"parent_id": False,

Choose a reason for hiding this comment

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

Wouldnt it be better to add all these directories under a common model directory Contacts Root for example instead of making every record root directory?

"root_storage_id": storage_id.id,
}

if dms_field and dms_field.state == "installed":
directory_fields["res_id"] = attachment_id.res_id
Comment on lines +31 to +32
Copy link
Member

Choose a reason for hiding this comment

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

IMO it's unnecessary because of (in the future) other addon use it, it's not necessary to add new field res_id in directory because record_ref contain it already.

Copy link
Member

Choose a reason for hiding this comment

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

I think the standard is to have res_model and res_id field. The record_ref can be a computed one, composed over the other 2.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, but actually don't exists this fields.
Do you think that it's necessary to remove record_ref and add: res_model and res_id fields?
It's necessary to add this fields only in directory or in file too? (now group all attachment in only one directory, it's enought?)

Copy link
Member

Choose a reason for hiding this comment

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

I think it's better to go with res_model and res_id fields, and the other one computed (stored). If res_model can be computed stored as well from the dms.directory, perfect. I understand that dms.directory can contain res_model and optionally res_id, isn't it?


return self.env["dms.directory"].create(directory_fields)
Comment on lines +21 to +34
Copy link
Member

Choose a reason for hiding this comment

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

IMO it's unnecessary but need to change some things in _create


@api.model
def create(self, vals):
if "dms_file" in vals and vals["dms_file"]:
del vals["dms_file"]
return super(IrAttachment, self).create(vals)
else:
attachment_id = super(IrAttachment, self).create(vals)
if "res_model" in vals:
storage_id = self.env["dms.storage"].search(
[("model_id", "=", vals["res_model"])]
)

if storage_id and storage_id.save_type == "attachment":
record_directory = self.env["dms.directory"].search(
[("complete_name", "=", attachment_id.res_name)]
)
if not record_directory:
record_directory = self._create_record_dir(
storage_id, attachment_id
)

attachments_dir_id = record_directory.child_directory_ids.filtered(
lambda r: r.name == "Attachments"
)

if not attachments_dir_id:
attachments_dir_id = self.env["dms.directory"].create(
{
"name": "Attachments",
"parent_id": record_directory.id,
"storage_id": storage_id.id,
"record_ref": "{},{}".format(
attachment_id.res_model, attachment_id.res_id
),
}
)
file_name = self._dms_file_name(attachments_dir_id, vals["name"])

self.env["dms.file"].create(
{
"name": file_name,
"directory_id": attachments_dir_id.id,
"attachment_id": attachment_id.id,
"record_ref": "{},{}".format(
attachment_id.res_model, attachment_id.res_id
),
}
)

return attachment_id
Comment on lines +36 to +85
Copy link
Member

Choose a reason for hiding this comment

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

In V12 change it for some reasons:

  • It's possible to exists some attachment storage
  • It's necessary to auto-create root directory related to model and storage
  • It's necessary to create sub directory (related to root directory previously auto-create) related to model and res_id with record_ref field.
  • Dms fIeld need to related to previous directory.
Suggested change
@api.model
def create(self, vals):
if "dms_file" in vals and vals["dms_file"]:
del vals["dms_file"]
return super(IrAttachment, self).create(vals)
else:
attachment_id = super(IrAttachment, self).create(vals)
if "res_model" in vals:
storage_id = self.env["dms.storage"].search(
[("model_id", "=", vals["res_model"])]
)
if storage_id and storage_id.save_type == "attachment":
record_directory = self.env["dms.directory"].search(
[("complete_name", "=", attachment_id.res_name)]
)
if not record_directory:
record_directory = self._create_record_dir(
storage_id, attachment_id
)
attachments_dir_id = record_directory.child_directory_ids.filtered(
lambda r: r.name == "Attachments"
)
if not attachments_dir_id:
attachments_dir_id = self.env["dms.directory"].create(
{
"name": "Attachments",
"parent_id": record_directory.id,
"storage_id": storage_id.id,
"record_ref": "{},{}".format(
attachment_id.res_model, attachment_id.res_id
),
}
)
file_name = self._dms_file_name(attachments_dir_id, vals["name"])
self.env["dms.file"].create(
{
"name": file_name,
"directory_id": attachments_dir_id.id,
"attachment_id": attachment_id.id,
"record_ref": "{},{}".format(
attachment_id.res_model, attachment_id.res_id
),
}
)
return attachment_id
@api.model
def create(self, vals):
if "dms_file" in vals and vals["dms_file"]:
del vals["dms_file"]
return super(IrAttachment, self).create(vals)
else:
attachment_id = super(IrAttachment, self).create(vals)
if attachment_id.res_model and attachment_id.res_id:
storage_ids = self.env["dms.storage"].search(
[
("model_id.model", "=", attachment_id.res_model),
("save_type", "=", "attachment"),
]
)
if storage_ids:
record_ref = "{},{}".format(
attachment_id.res_model, attachment_id.res_id,
)
directory_ids = self.env["dms.directory"].search(
[
("storage_id", "in", storage_ids.ids),
("record_ref", "=", record_ref),
]
)
if directory_ids:
directory_id = directory_ids[0]
else:
root_directory_ids = self.env["dms.directory"].search(
[
("storage_id", "=", storage_ids[0].id),
("is_root_directory", "=", True),
]
)
if root_directory_ids:
root_directory_id = root_directory_ids[0]
else:
root_directory_id = self.env["dms.directory"].create(
{
"name": attachment_id.res_model,
"is_root_directory": True,
"storage_id": storage_ids[0].id,
"root_storage_id": storage_ids[0].id,
}
)
# Create directory related to record_ref
directory_id = self.env["dms.directory"].create(
{
"name": attachment_id.res_name,
"parent_id": root_directory_id.id,
"storage_id": root_directory_id.storage_id.id,
"record_ref": record_ref,
}
)
# File operations + dms_file create
file_name = self._dms_file_name(directory_id, vals["name"])
self.env["dms.file"].create(
{
"name": file_name,
"directory_id": directory_id.id,
"attachment_id": attachment_id.id,
"record_ref": record_ref,
}
)
return attachment_id

8 changes: 7 additions & 1 deletion dms/models/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ class Storage(models.Model):
name = fields.Char(string="Name", required=True)

save_type = fields.Selection(
selection=[("database", _("Database")), ("file", _("Filestore"))],
selection=[
("database", _("Database")),
("file", _("Filestore")),
("attachment", _("Attachment")),
],
string="Save Type",
default="database",
required=True,
Expand Down Expand Up @@ -80,6 +84,8 @@ class Storage(models.Model):
compute="_compute_count_storage_files", string="Count Files"
)

model_id = fields.Many2one("ir.model", auto_join=True)

# ----------------------------------------------------------
# Actions
# ----------------------------------------------------------
Expand Down
6 changes: 6 additions & 0 deletions dms/views/directory.xml
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,12 @@
<field name="starred" widget="boolean_favorite" />
</group>
</group>
<group>
<field
name="record_ref"
attrs="{'invisible': [('file_ids', '=', [])]}"
/>
</group>
<notebook>
<page name="page_directories" string="Subdirectories">
<field
Expand Down
3 changes: 3 additions & 0 deletions dms/views/dms_file.xml
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,9 @@
/>
</group>
</group>
<group>
<field name="record_ref" />
</group>
<notebook>
<page name="page_meta" string="Meta Information">
<group>
Expand Down
4 changes: 4 additions & 0 deletions dms/views/storage.xml
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@
</group>
<group>
<field name="company_id" />
<field
name="model_id"
attrs="{'readonly': [('count_storage_directories', '>', 0)]}"
/>
</group>
</group>
<notebook>
Expand Down