You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
4.0 KiB

  1. # Copyright 2015 Florian DA COSTA @ Akretion
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  3. from base64 import b64decode
  4. import hashlib
  5. import logging
  6. from odoo import _, api, exceptions, fields, models, registry
  7. _logger = logging.getLogger(__name__)
  8. class IrAttachmentMetadata(models.Model):
  9. _name = 'ir.attachment.metadata'
  10. _inherits = {'ir.attachment': 'attachment_id'}
  11. _inherit = ['mail.thread']
  12. internal_hash = fields.Char(
  13. store=True, compute='_compute_hash',
  14. help="File hash computed with file data to be compared "
  15. "to external hash when provided.")
  16. external_hash = fields.Char(
  17. help="File hash comes from the external owner of the file.\n"
  18. "If provided allow to check than downloaded file "
  19. "is the exact copy of the original file.")
  20. attachment_id = fields.Many2one(
  21. 'ir.attachment', required=True, ondelete='cascade',
  22. help="Link to ir.attachment model ")
  23. file_type = fields.Selection(
  24. selection=[],
  25. help="The file type determines an import method to be used "
  26. "to parse and transform data before their import in ERP or an export")
  27. sync_date = fields.Datetime()
  28. state = fields.Selection([
  29. ('pending', 'Pending'),
  30. ('failed', 'Failed'),
  31. ('done', 'Done'),
  32. ], readonly=False, required=True, default='pending')
  33. state_message = fields.Text()
  34. @api.depends('datas', 'external_hash')
  35. def _compute_hash(self):
  36. for attachment in self:
  37. if attachment.datas:
  38. attachment.internal_hash = hashlib.md5(
  39. b64decode(attachment.datas)).hexdigest()
  40. if attachment.external_hash and\
  41. attachment.internal_hash != attachment.external_hash:
  42. raise exceptions.UserError(
  43. _("File corrupted: Something was wrong with "
  44. "the retrieved file, please relaunch the task."))
  45. @api.model
  46. def run_attachment_metadata_scheduler(self, domain=None):
  47. if domain is None:
  48. domain = [('state', '=', 'pending')]
  49. batch_limit = self.env.ref(
  50. 'attachment_base_synchronize.attachment_sync_cron_batch_limit') \
  51. .value
  52. if batch_limit and batch_limit.isdigit():
  53. limit = int(batch_limit)
  54. else:
  55. limit = 200
  56. attachments = self.search(domain, limit=limit)
  57. if attachments:
  58. return attachments.run()
  59. return True
  60. @api.multi
  61. def run(self):
  62. """
  63. Run the process for each attachment metadata
  64. """
  65. for attachment in self:
  66. with api.Environment.manage():
  67. with registry(self.env.cr.dbname).cursor() as new_cr:
  68. new_env = api.Environment(
  69. new_cr, self.env.uid, self.env.context)
  70. attach = attachment.with_env(new_env)
  71. try:
  72. attach._run()
  73. # pylint: disable=broad-except
  74. except Exception as e:
  75. attach.env.cr.rollback()
  76. _logger.exception(str(e))
  77. attach.write({
  78. 'state': 'failed',
  79. 'state_message': str(e),
  80. })
  81. attach.env.cr.commit()
  82. else:
  83. vals = {
  84. 'state': 'done',
  85. 'sync_date': fields.Datetime.now(),
  86. }
  87. attach.write(vals)
  88. attach.env.cr.commit()
  89. return True
  90. @api.multi
  91. def _run(self):
  92. self.ensure_one()
  93. _logger.info('Start to process attachment metadata id %d', self.id)
  94. @api.multi
  95. def set_done(self):
  96. """
  97. Manually set to done
  98. """
  99. message = "Manually set to done by %s" % self.env.user.name
  100. self.write({'state_message': message, 'state': 'done'})