i have odoo17 project and fastapi for api and i have problems with processing media files(photo,video) follow best practices and fix it: @router.get("/{application_id}", response_model=ApplicationDetail)
async def get_application_detail(
application_id: int,
env: Annotated[Environment, Depends(odoo_env)],
partner: Annotated[Partner, Depends(get_partner_with_session)],
):
Application = env['mahallam.application'].sudo()
application = Application.browse(application_id)

if not application.exists():
    raise HTTPException(status_code=404, detail=_("Application not found"))

return ApplicationDetail(
    id=application.id,
    status=application.status,
    description=application.description,
    date=application.created_at,
    category=application.category_id.name if application.category_id else None,
    subcategory=application.subcategory_id.name if application.subcategory_id else None,
    state=[(state.name, state.description) for state in application.state_id],
    images=[get_media_url(media._name, media.id, 'media') for media in application.image_ids],
    after_images=[get_media_url(media._name, media.id, 'media') for media in application.after_image_ids],
    is_author=application.partner_id.id == partner.id
)

@router.post("/create", response_model=ApplicationDetail)
async def create_application(
env: Annotated[Environment, Depends(odoo_env)],
partner: Annotated[Partner, Depends(get_partner_with_session)],
category_id: int = Form(...),
subcategory_id: int = Form(...),
description: str = Form(...),
latitude: float = Form(...),
longitude: float = Form(...),
media_files: List[UploadFile] = File(...),
):
Application = env['mahallam.application'].sudo()
ApplicationMedia = env['mahallam.application.media'].sudo()

main_home = partner.home_ids.filtered(lambda h: h.is_main_home)

application_vals = {
    'category_id': category_id,
    'subcategory_id': subcategory_id,
    'description': description,
    'latitude': latitude,
    'longitude': longitude,
    'status': 'created',
    'partner_id': partner.id,
}
if main_home:
    application_vals.update({
        'mahalla_id': main_home.home_id.mahalla_id.id,
        'district_id': main_home.home_id.district_id.id,
        'region_id': main_home.home_id.region_id.id,
    })

application = Application.create(application_vals)

for media_file in media_files:
    content = await media_file.read()
    ApplicationMedia.create({
        'application_id': application.id,
        'media': content,
        'media_name': media_file.filename
    })

return await get_application_detail(application.id, env, partner)from odoo import models, fields, api, _

import datetime

class Application(models.Model):
_name = 'mahallam.application'
_description = 'Application'

name = fields.Char(string=_('Nomi'))
partner_id = fields.Many2one('res.partner', string=_('Partner'), required=True, default=lambda self: self.env.user.partner_id)
category_id = fields.Many2one('mahallam.application.category', string=_('Category'))
subcategory_id = fields.Many2one('mahallam.application.subcategory', string=_('Subcategory'))
description = fields.Text(string=_('Description'), required=True)
image_ids = fields.One2many('mahallam.application.media', 'application_id', string=_('Images'), attachment=True)
after_image_ids = fields.One2many('mahallam.application.after.media', 'application_id', string=_('After Images'), attachment=True)
count_media = fields.Integer(string=_('Count Media'), compute='_compute_count_media')
status = fields.Selection(
    [
        ('created', _('Created')),
        ('completed', _('Completed')),
        ('in_progress', _('In Progress')),
        ('rejected', _('Rejected')),
        ('cancelled', _('Cancelled')),
    ],
    default="created"
)
state_id = fields.One2many('mahallam.application.state', 'application_id', string=_('Status'))
mahalla_id = fields.Many2one(
    'mahalla', string=_('Home Mahalla'), store=True, readonly=True
)
district_id = fields.Many2one(
    'district', string=_('Home District'), store=True, readonly=True
)
region_id = fields.Many2one(
    'region', string=_('Home Region'), store=True, readonly=True
)
created_at = fields.Datetime(string=_('Created At'), default=datetime.datetime.now())
latitude = fields.Float(string=_('Latitude'))
longitude = fields.Float(string=_('Latitude'))


@api.model
def write(self, vals):
    partner = self.env.user.partner_id
    main_home = partner.home_ids.filtered(lambda h: h.is_main_home)
    if main_home:
        vals.update({
            'mahalla_id': main_home.home_id.mahalla_id.id,
            'district_id': main_home.home_id.district_id.id,
            'region_id': main_home.home_id.region_id.id,
        })
    return super().write(vals)

def write(self, vals):
    res = super().write(vals)
    if 'status' in vals:
        self.env['mobile.app.push.notification'].create({
            'name': 'Application Status Update',
            'body': f'Your application #{self.id} status changed to {vals["status"]}',
            'notification_type': 'application_status',
            'model_name': 'mahallam.application',
            'object_id': self.id,
            'send_notification_to': 'to_partner',
            'partner_ids': [(6, 0, [self.create_uid.partner_id.id])]
        })
    return res

def _compute_count_media(self):
    for application in self:
        application.count_media = len(application.image_ids)

class ApplicationMedia(models.Model):
_name = 'mahallam.application.media'
_description = 'Application Media'

application_id = fields.Many2one('mahallam.application', string='Application', required=True, ondelete='cascade')
media = fields.Binary(string=_('Media'))
media_name = fields.Char(string=_('Name'))

class ApplicationAfterMedia(models.Model):
_name = 'mahallam.application.after.media'
_description = 'Application Media'

application_id = fields.Many2one('mahallam.application', string='Application', required=True, ondelete='cascade')
media = fields.Binary(string=_('Media'))
media_name = fields.Char(string=_('Name'))

class ApplicationCategory(models.Model):
_name = 'mahallam.application.category'
_description = 'Application Categories'

name = fields.Char(string=_('Nomi'))

class ApplicationSubcategory(models.Model):
_name = 'mahallam.application.subcategory'
_description = 'Application Subcategories'

name = fields.Char(string=_('Nomi'))
category_id = fields.Many2one('mahallam.application.category', string=_('Category'))

class ApplicationState(models.Model):
_name = 'mahallam.application.state'
_description = 'Application States'

name = fields.Selection(
    [
        ('created', _('Application Created')),
        ('application_sent', _('Application Sent')),
        ('started_work', _('Department Started Work')),
        ('ended_work', _('Department Ended Work')),
        ('message_sent', _('Message Sent')),
        ('was_addressed', _('Was Addressed')),
    ],
    default="created"
)
description = fields.Char(string=_('Description'))
application_id = fields.Many2one('mahallam.application', string=_('Application'))

from pydantic import BaseModel
from typing import Optional, List, Tuple
from datetime import datetime
from odoo.addons.fastapi_addon.schemas.base_schema import PagedCollection

class ApplicationBase(BaseModel):
id: int
status: str
description: str
date: datetime
category: Optional[str]
subcategory: Optional[str]

class ApplicationList(ApplicationBase):
photo: Optional[str]
is_author: bool

class ApplicationDetail(ApplicationBase):
state: List[Tuple[str, str]]
images: List[str]
after_images: List[str]

class ApplicationCreate(BaseModel):
category_id: int
subcategory_id: int
description: str
latitude: float
longitude: float

class UserApplicationsList(BaseModel):
applications: PagedCollection[ApplicationList]
total_count: int

class ApplicationCategoryBase(BaseModel):
id: int
name: str

class ApplicationSubcategoryBase(BaseModel):
id: int
name: str

class ApplicationCategoryWithSubcategories(BaseModel):
id: int
name: str
subcategories: List[ApplicationSubcategoryBase]
from ..settings import STAGE
import random
import string

def unique_str_generator(length=15):
characters = string.ascii_letters + string.digits
random_string = "".join(random.choice(characters) for _ in range(length))
return random_string

def get_media_url(model: str, object_id: int, field_name: str):
if STAGE == "production":
base_url = "https://mahallam-backend.uicgroup.tech"
else:
base_url = "http://localhost:8070"
return f"{base_url}/web/image/{model}/{object_id}/{field_name}/?{unique_str_generator(10)}",  give updates with commented highlights so that i could see them, and give complete files, dont change my get_media_url fiels, they used in many cases, if needed create custom, mediafiles could be both photo and video, i need image ids and after image ids in separate, heres complete router: import uuid
import logging
import base64
from typing import Optional, Annotated, List
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form, Request, status
from odoo.api import Environment
from odoo.addons.base.models.res_partner import Partner
from odoo.addons.fastapi_addon.schemas.base_schema import PagedCollection
from odoo.addons.fastapi_addon.utils.media_url import my_get_media_url as get_media_url
from odoo import _
from ..utils.validation import validate_file
from ..dependencies import odoo_env, get_partner_with_session
from ..schemas.tashabbuskor_schema import (
    ApplicationList,
    ApplicationDetail,
    ApplicationCreate,
    UserApplicationsList,
    ApplicationCategoryBase,
    ApplicationSubcategoryBase,
    ApplicationCategoryWithSubcategories
)



router = APIRouter(prefix="/applications", tags=["Applications"])
logger = logging.getLogger(__name__)

@router.get("/categories", response_model=List[ApplicationCategoryWithSubcategories])
async def get_application_categories_with_subcategories(
    env: Annotated[Environment, Depends(odoo_env)],
    partner: Annotated[Partner, Depends(get_partner_with_session)],
):
    """
    Get list of all available application categories with their subcategories
    """
    # Odoo model classes
    ApplicationCategory = env['mahallam.application.category'].sudo()
    ApplicationSubcategory = env['mahallam.application.subcategory'].sudo()
    
    # Fetch categories
    categories = ApplicationCategory.search([])
    
    # Prepare the response
    response = []
    for category in categories:
        # Fetch subcategories for each category
        subcategories = ApplicationSubcategory.search([('category_id', '=', category.id)])
        
        # Append category with nested subcategories to the response list
        response.append(
            ApplicationCategoryWithSubcategories(
                id=category.id,
                name=category.name,
                subcategories=[
                    ApplicationSubcategoryBase(
                        id=subcategory.id,
                        name=subcategory.name
                    )
                    for subcategory in subcategories
                ]
            )
        )
        
    return response

@router.get("/list", response_model=PagedCollection[ApplicationList])
async def get_applications_list(
        env: Annotated[Environment, Depends(odoo_env)],
        partner: Annotated[Partner, Depends(get_partner_with_session)],
        request: Request,
):
    Application = env['mahallam.application'].sudo()
    main_home = env['user.home.session'].sudo().search([
        ('partner_id', '=', partner.id),
        ('is_main_home', '=', True)
    ], limit=1)



    if not main_home:
        raise HTTPException(status_code=404, detail=_("Main home not found"))

    domain = [('mahalla_id', '=', main_home.home_id.mahalla_id.id)]
    applications = Application.search(domain)

    items = [
        ApplicationList(
            id=app.id,
            status=app.status,
            photo=get_media_url(app.image_ids[0]._name, app.image_ids[0].id, 'media') if app.image_ids else None,
            description=app.description,
            date=app.created_at,
            category=app.category_id.name if app.category_id else None,
            subcategory=app.subcategory_id.name if app.subcategory_id else None,
            is_author=app.partner_id.id == partner.id,
        )
        for app in applications
    ]

    return PagedCollection[ApplicationList](
        count=len(applications),
        current=str(request.url),
        items=items
    )


@router.get("/my", response_model=UserApplicationsList)
async def get_user_applications(
        env: Annotated[Environment, Depends(odoo_env)],
        partner: Annotated[Partner, Depends(get_partner_with_session)],
        request: Request,
):
    Application = env['mahallam.application'].sudo()
    main_home = env['user.home.session'].sudo().search([
        ('partner_id', '=', partner.id),
        ('is_main_home', '=', True)
    ], limit=1)
    domain = [('partner_id', '=', partner.id),('mahalla_id', '=', main_home.home_id.mahalla_id.id)]
    applications = Application.search(domain)

    items = [
        ApplicationList(
            id=app.id,
            status=app.status,
            photo=get_media_url(app.image_ids[0]._name, app.image_ids[0].id, 'media') if app.image_ids else None,
            description=app.description,
            date=app.created_at,
            category=app.category_id.name if app.category_id else None,
            subcategory=app.subcategory_id.name if app.subcategory_id else None,
            is_author=app.partner_id.id == partner.id
        )
        for app in applications
    ]

    return UserApplicationsList(
        applications=PagedCollection[ApplicationList](
            count=len(applications),
            current=str(request.url),
            items=items
        ),
        total_count=len(applications)
    )


@router.get("/{application_id}", response_model=ApplicationDetail)
async def get_application_detail(
        application_id: int,
        env: Environment = Depends(odoo_env),
        partner: Partner = Depends(get_partner_with_session),
):
    Application = env['mahallam.application'].sudo()
    application = Application.browse(application_id)

    if not application.exists():
        logger.warning(f"Application with ID {application_id} not found.")
        raise HTTPException(status_code=404, detail="Application not found")

    try:
        # Fetch attachments related to the application
        media_attachments = env['ir.attachment'].sudo().search([
            ('res_model', '=', 'mahallam.application'),
            ('res_id', '=', application.id)
        ])

        application_detail = ApplicationDetail(
            id=application.id,
            status=application.status,
            description=application.description,
            date=application.created_at,
            category=application.category_id.name if application.category_id else None,
            subcategory=application.subcategory_id.name if application.subcategory_id else None,
            state=[(state.name, state.description) for state in application.state_id],
            media=[my_get_media_url(attachment.id) for attachment in media_attachments],
            is_author=application.partner_id.id == partner.id
        )
        return application_detail
    except Exception as e:
        logger.error(f"Error retrieving application details for ID {application_id}: {str(e)}")
        raise HTTPException(status_code=500, detail="Internal Server Error")

@router.post("/create", response_model=ApplicationDetail, status_code=status.HTTP_201_CREATED)
async def create_application(
        env: Environment = Depends(odoo_env),
        partner: Partner = Depends(get_partner_with_session),
        category_id: int = Form(...),
        subcategory_id: int = Form(...),
        description: str = Form(...),
        latitude: float = Form(...),
        longitude: float = Form(...),
        media_files: List[UploadFile] = File(...),
):
    Application = env['mahallam.application'].sudo()

    # Prepare application values
    application_vals = {
        'category_id': category_id,
        'subcategory_id': subcategory_id,
        'description': description,
        'latitude': latitude,
        'longitude': longitude,
        'status': 'created',
        'partner_id': partner.id,
    }

    # Get main home details
    main_home = partner.home_ids.filtered(lambda h: h.is_main_home)
    if main_home:
        application_vals.update({
            'mahalla_id': main_home.home_id.mahalla_id.id,
            'district_id': main_home.home_id.district_id.id,
            'region_id': main_home.home_id.region_id.id,
        })

    try:
        # Create the application record
        application = Application.create(application_vals)
        logger.info(f"Created application with ID {application.id} for partner {partner.id}")

        # Process and attach each media file
        for media_file in media_files:
            validate_file(media_file)  # Validate the file

            unique_filename = f"{uuid.uuid4()}_{media_file.filename}"
            file_content = await media_file.read()

            # Encode binary data to base64 as Odoo expects base64 encoded content for binary fields
            encoded_content = base64.b64encode(file_content).decode('utf-8')

            # Create attachment
            attachment = env['ir.attachment'].sudo().create({
                'name': unique_filename,
                'type': 'binary',
                'datas': encoded_content,
                'res_model': 'mahallam.application',
                'res_id': application.id,
                'mimetype': media_file.content_type,
                'store_fname': unique_filename,
                'unique': True,
                'public': False,  # Change to True if files should be publicly accessible
            })

            # Link attachment to the application
            application.media_ids = [(4, attachment.id)]
            logger.info(f"Attached file {unique_filename} to application ID {application.id}")

        return await get_application_detail(application.id, env, partner)

    except HTTPException as he:
        logger.error(f"HTTPException during application creation: {he.detail}")
        raise he
    except Exception as e:
        logger.error(f"Error creating application: {str(e)}")
        raise HTTPException(status_code=500, detail="Internal Server Error")


@router.post("/{application_id}/complete", response_model=ApplicationDetail)
async def complete_application(
        application_id: int,
        env: Annotated[Environment, Depends(odoo_env)],
        partner: Annotated[Partner, Depends(get_partner_with_session)],
):
    Application = env['mahallam.application'].sudo()
    application = Application.browse(application_id)

    if not application.exists():
        raise HTTPException(status_code=404, detail=_("Application not found"))

    if application.partner_id.id != partner.id:
        raise HTTPException(status_code=403, detail=_("Not authorized to complete this application"))

    if application.status not in ['created', 'in_progress']:
        raise HTTPException(
            status_code=400,
            detail=f"Cannot complete application in {application.status} status")

    application.write({'status': 'completed'})

    return await get_application_detail(application_id, env, partner)

@router.post("/{application_id}/cancel", response_model=ApplicationDetail)
async def cancel_application(
        application_id: int,
        env: Annotated[Environment, Depends(odoo_env)],
        partner: Annotated[Partner, Depends(get_partner_with_session)],
):
    Application = env['mahallam.application'].sudo()
    application = Application.browse(application_id)

    if not application.exists():
        raise HTTPException(status_code=404, detail=_("Application not found"))

    if application.partner_id.id != partner.id:
        raise HTTPException(status_code=403, detail=_("Not authorized to cancel this application"))

    if application.status not in ['created', 'in_progress']:
        raise HTTPException(
            status_code=400,
            detail=f"Cannot cancel application in {application.status} status"
        )

    application.write({'status': 'cancelled'})

    return await get_application_detail(application_id, env, partner)