Odoo Flutter Mobile App using EKIKA's API Framework
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.
 
 
 
 
 
 

263 lines
8.5 KiB

import 'dart:convert';
import 'package:http/http.dart' as http;
// final String API_URL = DataEndpoint;
// final String API_KEY = '''Af+"E<y.-Rs<q9")|'%7A&@U.fU}JV~:''';
class SyncError implements Exception {
final String message;
SyncError([this.message = 'Connection not established.']);
@override
String toString() {
return 'Sync Error: $message';
}
}
class EasyAPIClient {
late String apiurl;
late String apikey;
late Map<String, String> headers;
EasyAPIClient(apiurl, apikey) {
this.apiurl = apiurl;
this.apikey = apikey;
this.headers = {
'x-api-key': apikey,
'Content-Type': 'application/json',
};
}
Future<http.Response> post(String query, [Map<String, dynamic> variables = const {}]) async {
final allbodyparts = {'query': query, 'variables': variables};
final body = Map.fromEntries(allbodyparts.entries.where((entry) => entry.value != null));
return await http.post(Uri.parse(this.apiurl), headers: this.headers, body: jsonEncode(body));
}
}
String pyDictToGPLString(dynamic values, [int indent = 0]) {
String formatValue(dynamic value, [int indent = 0]) {
if (value is bool) {
return value.toString().toLowerCase();
} else if (value is String) {
return '"$value"';
} else if (value is List) {
final items = value.map((item) => formatValue(item, indent)).join(', ');
return '[$items]';
} else if (value is Map) {
final items = value.entries.map((entry) => ' ' * (indent + 1) + '${entry.key}: ${formatValue(entry.value, indent + 1)}').join(',\n');
return '{\n$items\n${' ' * indent}}';
} else {
return value.toString();
}
}
final formattedValues = formatValue(values, indent);
return formattedValues;
}
String pyDictToGPLQueryString(Map<String, dynamic> querydict, [int indent = 1]) {
String generateQueryString(Map<String, dynamic> querydict, [int indent = 1]) {
var queryString = '';
querydict.forEach((key, value) {
if (value == null) {
queryString += ' ' * indent + '$key\n';
} else if (value is Map<String, dynamic>) {
queryString += ' ' * indent + '$key {\n';
queryString += generateQueryString(value, indent + 1);
queryString += ' ' * indent + '}\n';
} else {
throw ArgumentError('Invalid querydict format');
}
});
return queryString;
}
final queryString = generateQueryString(querydict, indent);
return '{\n$queryString${' ' * (indent - 1)}}';
}
class GPLModel {
late EasyAPIClient _syncapi;
final String omodel;
late String gpl_model;
GPLModel(this.omodel, String apiurl, String apikey) {
if (omodel.isNotEmpty) {
gpl_model = convertToCamelCase(omodel);
_syncapi = EasyAPIClient(apiurl, apikey);
}
else {
gpl_model = "";
}
}
String convertToCamelCase(String input) {
List<String> parts = input.split('.');
List<String> capitalizedParts = parts.map((part) {
if (part.isNotEmpty) {
return part[0].toUpperCase() + part.substring(1);
} else {
return '';
}
}).toList();
return capitalizedParts.join();
}
Future<Map<String, dynamic>> browse({required int id, Map<String, dynamic> querydict = const {'id': null}}) async {
final gplquery = pyDictToGPLQueryString(querydict, 2);
final browseBody = '''query MyQuery {
$gpl_model(id: "$id") $gplquery
}''';
final response = await _syncapi.post(browseBody);
final data = json.decode(response.body)['data'];
return data[gpl_model][0];
}
Future<List<dynamic>> search({List<List<dynamic>> domain = const [], String order = 'name', int limit = 80, int offset = 0, Map<String, dynamic> querydict = const {'id': null}}) async {
final gplquery = pyDictToGPLQueryString(querydict, 2);
final searchBody = '''query MyQuery(\$offset: Int, \$limit: Int, \$order: String, \$domain: [[Any]]) {
$gpl_model(
offset: \$offset
limit: \$limit
order: \$order
domain: \$domain
) $gplquery
}''';
final allVariables = {
'domain': domain,
'order': order,
'limit': limit,
'offset': offset,
};
final response = await _syncapi.post(searchBody, allVariables);
final data = json.decode(response.body)['data'];
return data[gpl_model];
}
Future<Map<String, dynamic>> create({Map<String, dynamic> values = const {}, Map<String, dynamic> querydict = const {'id': null}}) async {
final gplvalues = pyDictToGPLString(values, 2);
final gplquery = pyDictToGPLQueryString(querydict, 2);
print(gpl_model);
final createBody = '''mutation Create {
create$gpl_model: $gpl_model(
$gpl_model\Values: $gplvalues
) $gplquery
}''';
final response = await _syncapi.post(createBody);
final data = json.decode(response.body)['data'];
return data['create$gpl_model'][0];
}
Future<Map<String, dynamic>> write({required int id, required Map<String, dynamic> values, Map<String, dynamic> querydict = const {'id': null}}) async {
final gplvalues = pyDictToGPLString(values, 2);
final gplquery = pyDictToGPLQueryString(querydict, 2);
final writeBody = '''mutation Update {
update$gpl_model: $gpl_model(
id: $id,
$gpl_model\Values: $gplvalues
) $gplquery
}''';
final response = await _syncapi.post(writeBody);
final data = json.decode(response.body)['data'];
return data['update$gpl_model'][0];
}
Future<Map<String, dynamic>> delete({required int id, Map<String, dynamic> querydict = const {'id': null}}) async {
final gplquery = pyDictToGPLQueryString(querydict, 2);
final deleteBody = '''mutation Delete {
delete$gpl_model: $gpl_model(
id: $id
) $gplquery
}''';
final response = await _syncapi.post(deleteBody);
final data = json.decode(response.body);
return data;
}
Future<Map<String, dynamic>> methodExecute(int id, String methodName, Map<String, dynamic> methodParameters) async {
final methodExecuteBody = '''mutation Method {
method$gpl_model: $gpl_model(
id: $id,
method_name: $methodName,
method_parameters: ${pyDictToGPLString(methodParameters)}
)
}''';
final response = await _syncapi.post(methodExecuteBody);
final data = json.decode(response.body);
return data;
}
}
Future<dynamic> makeApiLoginRequest({required String username,required String password, required baseEndpoint, required authEndpoint}) async {
Map<String, dynamic> jsonData = {
'base_endpoint': baseEndpoint,
};
String basicAuth = 'Basic ' + base64Encode(utf8.encode('$username:$password'));
Map<String, String> headers = {
'Content-Type': 'application/json',
'Authorization': basicAuth,
};
String jsonEncoded = json.encode(jsonData);
try{
var response = await http.post(
Uri.parse(authEndpoint),
headers: headers,
body: jsonEncoded,
);
return response;
} catch(e) {
print(e);
}
}
// final GPLModel resObj = GPLModel('res.partner');
// void main() {
// // For normal query operation
// var query_dict = {'id': null, 'name': null, 'country_id': {'id': null, 'name': null}, 'mobile': null};
// // final result = resObj.search(domain: const [], querydict: query_dict);
// final result = resObj.browse(1079, query_dict);
// // final create_values = {
// // 'active': true,
// // 'name': 'Ekika Corporation PVT LTD.',
// // 'bank_ids': [
// // [0, 0, {
// // 'sequence': 10,
// // 'bank_id': 2,
// // 'acc_number': '1111111',
// // 'allow_out_payment': true,
// // 'acc_holder_name': false,
// // }],
// // [0, 0, {
// // 'sequence': 10,
// // 'bank_id': 3,
// // 'acc_number': '9999999999999',
// // 'allow_out_payment': true,
// // 'acc_holder_name': false,
// // }]
// // ],
// // 'city': 'Gandhinagar',
// // 'zip': '382421',
// // 'comment': '<h3>Comment Here</h3>',
// // 'mobile': '888888888',
// // };
// // final result = resObj.create(values: create_values, querydict: query_dict);
// // final write_values = {
// // 'name': 'Ekika Corporation',
// // 'mobile': 111111111,
// // };
// // final result = resObj.write(1115, write_values,query_dict);
// // final result = resObj.delete(1116);
// // final result = resObj.methodExecute(4, 'parameter_test_method', {'key_3': 'new_val_3', 'key_2': 'new_val_2', 'key_1': 'new_val_1'});
// result.then((value) => print(value));
// // You can call other functions here like resWriteOne.
// }