@ -21,6 +21,7 @@
#############################################################################
#############################################################################
import json
import json
import logging
import logging
import base64
from odoo import http
from odoo import http
from odoo . http import request
from odoo . http import request
from datetime import datetime , date
from datetime import datetime , date
@ -46,21 +47,65 @@ class RestApi(http.Controller):
" !</h2></body></html> " )
" !</h2></body></html> " )
return response
return response
def generate_response ( self , method , model , rec_id ) :
def generate_response ( self , method , model , rec_id , request_params = None ) :
""" This function is used to generate the response based on the type
""" This function is used to generate the response based on the type
of request and the parameters given """
of request and the parameters given """
option = request . env [ ' connection.api ' ] . search (
option = request . env [ ' connection.api ' ] . search (
[ ( ' model_id ' , ' = ' , model ) ] , limit = 1 )
[ ( ' model_id ' , ' = ' , model ) ] , limit = 1 )
model_name = option . model_id . model
model_name = option . model_id . model
if method != ' DELETE ' :
data = json . loads ( request . httprequest . data )
# Handle data based on method
if method == ' GET ' :
# For GET requests, check both JSON body and query parameters
data = request_params or { }
fields = [ ]
# First, try to get fields from JSON body
try :
if request . httprequest . data :
json_data = json . loads ( request . httprequest . data )
if ' fields ' in json_data :
fields = json_data [ ' fields ' ]
except json . JSONDecodeError :
pass # If JSON is invalid, continue with query params
# If no fields from JSON, try query parameters
if not fields :
fields_param = data . get ( ' fields ' , ' ' )
if fields_param :
fields = [ field . strip ( ) for field in fields_param . split ( ' , ' ) ]
# If still no fields, use defaults based on record type
if not fields :
if rec_id != 0 :
# For specific record, get all fields
fields = None # This will get all available fields
else :
# For all records, use minimal fields
fields = [ ' id ' , ' display_name ' ]
elif method != ' DELETE ' :
# For POST/PUT requests, parse JSON from body
try :
if request . httprequest . data :
data = json . loads ( request . httprequest . data )
else :
data = { }
except json . JSONDecodeError :
return ( " <html><body><h2>Invalid JSON Data "
" </h2></body></html> " )
else :
else :
# DELETE method
data = { }
data = { }
fields = [ ]
fields = [ ]
if data :
for field in data [ ' fields ' ] :
# Extract fields for POST/PUT methods
fields . append ( field )
if method in [ ' POST ' , ' PUT ' ] and data :
if not fields and method != ' DELETE ' :
fields = [ ]
if ' fields ' in data :
for field in data [ ' fields ' ] :
fields . append ( field )
if not fields and method != ' DELETE ' and method != ' GET ' :
return ( " <html><body><h2>No fields selected for the model "
return ( " <html><body><h2>No fields selected for the model "
" </h2></body></html> " )
" </h2></body></html> " )
if not option :
if not option :
@ -68,34 +113,55 @@ class RestApi(http.Controller):
" </h2></body></html> " )
" </h2></body></html> " )
try :
try :
if method == ' GET ' :
if method == ' GET ' :
fields = [ ]
for field in data [ ' fields ' ] :
fields . append ( field )
if not option . is_get :
if not option . is_get :
return ( " <html><body><h2>Method Not Allowed "
return ( " <html><body><h2>Method Not Allowed "
" </h2></body></html> " )
" </h2></body></html> " )
else :
else :
datas = [ ]
datas = [ ]
if rec_id != 0 :
if rec_id != 0 :
# For specific record
search_fields = fields if fields is not None else [ ]
partner_records = request . env [
partner_records = request . env [
str ( model_name ) ] . search_read (
str ( model_name ) ] . search_read (
domain = [ ( ' id ' , ' = ' , rec_id ) ] ,
domain = [ ( ' id ' , ' = ' , rec_id ) ] ,
fields = fields
fields = search_ fields
)
)
for record in partner_records :
for record in partner_records :
for key , value in record . items ( ) :
for key , value in record . items ( ) :
if isinstance ( value , ( datetime , date ) ) :
if isinstance ( value , ( datetime , date ) ) :
record [ key ] = value . isoformat ( )
record [ key ] = value . isoformat ( )
elif isinstance ( value , bytes ) :
# Convert bytes to base64 string for JSON serialization
import base64
record [ key ] = base64 . b64encode ( value ) . decode ( ' utf-8 ' )
elif hasattr ( value , ' __iter__ ' ) and not isinstance ( value , ( str , dict ) ) :
# Handle other non-serializable iterables
try :
record [ key ] = list ( value ) if value else [ ]
except :
record [ key ] = str ( value )
elif isinstance ( value , bytes ) :
# Convert bytes to base64 string for JSON serialization
import base64
record [ key ] = base64 . b64encode ( value ) . decode ( ' utf-8 ' )
elif hasattr ( value , ' __iter__ ' ) and not isinstance ( value , ( str , dict ) ) :
# Handle other non-serializable iterables
try :
record [ key ] = list ( value ) if value else [ ]
except :
record [ key ] = str ( value )
data = json . dumps ( {
data = json . dumps ( {
' records ' : partner_records
' records ' : partner_records
} )
} )
datas . append ( data )
datas . append ( data )
return request . make_response ( data = datas )
return request . make_response ( data = datas )
else :
else :
# For all records
search_fields = fields if fields is not None else [ ' id ' , ' display_name ' ]
partner_records = request . env [
partner_records = request . env [
str ( model_name ) ] . search_read (
str ( model_name ) ] . search_read (
domain = [ ] ,
domain = [ ] ,
fields = fields
fields = search_ fields
)
)
for record in partner_records :
for record in partner_records :
for key , value in record . items ( ) :
for key , value in record . items ( ) :
@ -106,16 +172,17 @@ class RestApi(http.Controller):
} )
} )
datas . append ( data )
datas . append ( data )
return request . make_response ( data = datas )
return request . make_response ( data = datas )
except :
except Exception as e :
return ( " <html><body><h2>Invalid JSON Data "
_logger . error ( f " Error in GET method: { str ( e ) } " )
return ( " <html><body><h2>Error processing request "
" </h2></body></html> " )
" </h2></body></html> " )
if method == ' POST ' :
if method == ' POST ' :
if not option . is_post :
if not option . is_post :
return ( " <html><body><h2>Method Not Allowed "
return ( " <html><body><h2>Method Not Allowed "
" </h2></body></html> " )
" </h2></body></html> " )
else :
else :
try :
try :
data = json . loads ( request . httprequest . data )
datas = [ ]
datas = [ ]
new_resource = request . env [ str ( model_name ) ] . create (
new_resource = request . env [ str ( model_name ) ] . create (
data [ ' values ' ] )
data [ ' values ' ] )
@ -128,12 +195,34 @@ class RestApi(http.Controller):
for key , value in record . items ( ) :
for key , value in record . items ( ) :
if isinstance ( value , ( datetime , date ) ) :
if isinstance ( value , ( datetime , date ) ) :
record [ key ] = value . isoformat ( )
record [ key ] = value . isoformat ( )
elif isinstance ( value , bytes ) :
# Convert bytes to base64 string for JSON serialization
import base64
record [ key ] = base64 . b64encode ( value ) . decode ( ' utf-8 ' )
elif hasattr ( value , ' __iter__ ' ) and not isinstance ( value , ( str , dict ) ) :
# Handle other non-serializable iterables
try :
record [ key ] = list ( value ) if value else [ ]
except :
record [ key ] = str ( value )
elif isinstance ( value , bytes ) :
# Convert bytes to base64 string for JSON serialization
import base64
record [ key ] = base64 . b64encode ( value ) . decode ( ' utf-8 ' )
elif hasattr ( value , ' __iter__ ' ) and not isinstance ( value , ( str , dict ) ) :
# Handle other non-serializable iterables
try :
record [ key ] = list ( value ) if value else [ ]
except :
record [ key ] = str ( value )
new_data = json . dumps ( { ' New resource ' : partner_records , } )
new_data = json . dumps ( { ' New resource ' : partner_records , } )
datas . append ( new_data )
datas . append ( new_data )
return request . make_response ( data = datas )
return request . make_response ( data = datas )
except :
except Exception as e :
_logger . error ( f " Error in POST method: { str ( e ) } " )
return ( " <html><body><h2>Invalid JSON Data "
return ( " <html><body><h2>Invalid JSON Data "
" </h2></body></html> " )
" </h2></body></html> " )
if method == ' PUT ' :
if method == ' PUT ' :
if not option . is_put :
if not option . is_put :
return ( " <html><body><h2>Method Not Allowed "
return ( " <html><body><h2>Method Not Allowed "
@ -151,7 +240,6 @@ class RestApi(http.Controller):
else :
else :
try :
try :
datas = [ ]
datas = [ ]
data = json . loads ( request . httprequest . data )
resource . write ( data [ ' values ' ] )
resource . write ( data [ ' values ' ] )
partner_records = request . env [
partner_records = request . env [
str ( model_name ) ] . search_read (
str ( model_name ) ] . search_read (
@ -162,15 +250,37 @@ class RestApi(http.Controller):
for key , value in record . items ( ) :
for key , value in record . items ( ) :
if isinstance ( value , ( datetime , date ) ) :
if isinstance ( value , ( datetime , date ) ) :
record [ key ] = value . isoformat ( )
record [ key ] = value . isoformat ( )
elif isinstance ( value , bytes ) :
# Convert bytes to base64 string for JSON serialization
import base64
record [ key ] = base64 . b64encode ( value ) . decode ( ' utf-8 ' )
elif hasattr ( value , ' __iter__ ' ) and not isinstance ( value , ( str , dict ) ) :
# Handle other non-serializable iterables
try :
record [ key ] = list ( value ) if value else [ ]
except :
record [ key ] = str ( value )
elif isinstance ( value , bytes ) :
# Convert bytes to base64 string for JSON serialization
import base64
record [ key ] = base64 . b64encode ( value ) . decode ( ' utf-8 ' )
elif hasattr ( value , ' __iter__ ' ) and not isinstance ( value , ( str , dict ) ) :
# Handle other non-serializable iterables
try :
record [ key ] = list ( value ) if value else [ ]
except :
record [ key ] = str ( value )
new_data = json . dumps (
new_data = json . dumps (
{ ' Updated resource ' : partner_records ,
{ ' Updated resource ' : partner_records ,
} )
} )
datas . append ( new_data )
datas . append ( new_data )
return request . make_response ( data = datas )
return request . make_response ( data = datas )
except :
except Exception as e :
_logger . error ( f " Error in PUT method: { str ( e ) } " )
return ( " <html><body><h2>Invalid JSON Data "
return ( " <html><body><h2>Invalid JSON Data "
" !</h2></body></html> " )
" !</h2></body></html> " )
if method == ' DELETE ' :
if method == ' DELETE ' :
if not option . is_delete :
if not option . is_delete :
return ( " <html><body><h2>Method Not Allowed "
return ( " <html><body><h2>Method Not Allowed "
@ -186,7 +296,6 @@ class RestApi(http.Controller):
return ( " <html><body><h2>Resource not found "
return ( " <html><body><h2>Resource not found "
" </h2></body></html> " )
" </h2></body></html> " )
else :
else :
records = request . env [
records = request . env [
str ( model_name ) ] . search_read (
str ( model_name ) ] . search_read (
domain = [ ( ' id ' , ' = ' , resource . id ) ] ,
domain = [ ( ' id ' , ' = ' , resource . id ) ] ,
@ -227,7 +336,8 @@ class RestApi(http.Controller):
rec_id = 0
rec_id = 0
else :
else :
rec_id = int ( kw . get ( ' Id ' ) )
rec_id = int ( kw . get ( ' Id ' ) )
result = self . generate_response ( http_method , model_id . id , rec_id )
# Pass the query parameters for GET requests
result = self . generate_response ( http_method , model_id . id , rec_id , kw )
return result
return result
else :
else :
return auth_api
return auth_api
@ -252,6 +362,7 @@ class RestApi(http.Controller):
" User " : user . name ,
" User " : user . name ,
" api-key " : api_key } )
" api-key " : api_key } )
return request . make_response ( data = datas )
return request . make_response ( data = datas )
except :
except Exception as e :
_logger . error ( f " Error in authentication: { str ( e ) } " )
return ( " <html><body><h2>wrong login credentials "
return ( " <html><body><h2>wrong login credentials "
" </h2></body></html> " )
" </h2></body></html> " )