# -*- coding: utf-8 -*- from odoo import api, fields, models, _ from odoo.exceptions import UserError import base64 import logging _logger = logging.getLogger(__name__) class ADPDocument(models.Model): _name = 'fusion.adp.document' _description = 'ADP Application Document' _order = 'upload_date desc, revision desc' _rec_name = 'display_name' # Relationships sale_order_id = fields.Many2one( 'sale.order', string='Sale Order', ondelete='cascade', index=True, ) assessment_id = fields.Many2one( 'fusion.assessment', string='Assessment', ondelete='cascade', index=True, ) # Document Type document_type = fields.Selection([ ('full_application', 'Full ADP Application (14 pages)'), ('pages_11_12', 'Pages 11 & 12 (Signature Pages)'), ('page_11', 'Page 11 Only (Authorizer Signature)'), ('page_12', 'Page 12 Only (Client Signature)'), ('submitted_final', 'Final Submitted Application'), ('assessment_report', 'Assessment Report'), ('assessment_signed', 'Signed Pages from Assessment'), ('other', 'Other Document'), ], string='Document Type', required=True, default='full_application') # File Data file = fields.Binary( string='File', required=True, attachment=True, ) filename = fields.Char( string='Filename', required=True, ) file_size = fields.Integer( string='File Size (bytes)', compute='_compute_file_size', store=True, ) mimetype = fields.Char( string='MIME Type', default='application/pdf', ) # Revision Tracking revision = fields.Integer( string='Revision', default=1, readonly=True, ) revision_note = fields.Text( string='Revision Note', help='Notes about what changed in this revision', ) is_current = fields.Boolean( string='Is Current Version', default=True, index=True, ) # Upload Information uploaded_by = fields.Many2one( 'res.users', string='Uploaded By', default=lambda self: self.env.user, readonly=True, ) upload_date = fields.Datetime( string='Upload Date', default=fields.Datetime.now, readonly=True, ) source = fields.Selection([ ('authorizer', 'Authorizer Portal'), ('sales_rep', 'Sales Rep Portal'), ('internal', 'Internal User'), ('assessment', 'Assessment Form'), ], string='Source', default='internal') # Display display_name = fields.Char( string='Display Name', compute='_compute_display_name', store=True, ) @api.depends('file') def _compute_file_size(self): for doc in self: if doc.file: doc.file_size = len(base64.b64decode(doc.file)) else: doc.file_size = 0 @api.depends('document_type', 'filename', 'revision') def _compute_display_name(self): type_labels = dict(self._fields['document_type'].selection) for doc in self: type_label = type_labels.get(doc.document_type, doc.document_type) doc.display_name = f"{type_label} - v{doc.revision} ({doc.filename or 'No file'})" @api.model_create_multi def create(self, vals_list): """Override create to handle revision numbering""" for vals in vals_list: # Find existing documents of the same type for the same order/assessment domain = [('document_type', '=', vals.get('document_type'))] if vals.get('sale_order_id'): domain.append(('sale_order_id', '=', vals.get('sale_order_id'))) if vals.get('assessment_id'): domain.append(('assessment_id', '=', vals.get('assessment_id'))) existing = self.search(domain, order='revision desc', limit=1) if existing: # Mark existing as not current and increment revision existing.is_current = False vals['revision'] = existing.revision + 1 else: vals['revision'] = 1 vals['is_current'] = True return super().create(vals_list) def action_download(self): """Download the document""" self.ensure_one() return { 'type': 'ir.actions.act_url', 'url': f'/web/content/{self._name}/{self.id}/file/{self.filename}?download=true', 'target': 'self', } def get_document_url(self): """Get the download URL for portal access""" self.ensure_one() return f'/my/authorizer/document/{self.id}/download' @api.model def get_documents_for_order(self, sale_order_id, document_type=None, current_only=True): """Get documents for a sale order, optionally filtered by type""" domain = [('sale_order_id', '=', sale_order_id)] if document_type: domain.append(('document_type', '=', document_type)) if current_only: domain.append(('is_current', '=', True)) return self.search(domain, order='document_type, revision desc') @api.model def get_revision_history(self, sale_order_id, document_type): """Get all revisions of a specific document type""" return self.search([ ('sale_order_id', '=', sale_order_id), ('document_type', '=', document_type), ], order='revision desc')