import 'dart:async'; import 'dart:convert'; import 'package:http/http.dart' as http; /// Klien JSON-RPC utk Odoo 17. Authenticate + execute_kw. class OdooClient { OdooClient({required this.baseUrl, required this.db, required this.username, required this.password}) : _http = http.Client(); final String baseUrl; // mis: http://192.168.x.x:18069 final String db; // nama db, default 'odoo' final String username; final String password; final http.Client _http; int? _uid; Uri get _endpoint => Uri.parse('$baseUrl/jsonrpc'); Future authenticate() async { final result = await _call('common', 'authenticate', [db, username, password, {}]); if (result is int && result > 0) { _uid = result; return result; } throw Exception('Login gagal: periksa kredensial / URL Odoo'); } Future executeKwd(String model, String method, {List args = const [], Map? kwargs}) async { _uid ??= await authenticate(); final params = [ db, _uid, password, model, method, args, if (kwargs != null) kwargs, ]; return _call('object', 'execute_kw', params); } Future _call(String service, String method, List args) async { final body = { 'jsonrpc': '2.0', 'method': 'call', 'params': { 'service': service, 'method': method, 'args': args, }, }; try { final resp = await _http .post(_endpoint, headers: {'Content-Type': 'application/json'}, body: jsonEncode(body)) .timeout(const Duration(seconds: 25)); final json = jsonDecode(resp.body) as Map; if (json.containsKey('error')) { final err = json['error'] as Map?; String? message = (err?['data'] as Map?)?['message'] as String? ?? (err?['message'] as String?) ?? 'Unknown Odoo error'; throw Exception('Odoo error: $message'); } return json['result']; } on TimeoutException { throw Exception('Timeout — pastikan server Odoo:18069 tercapai'); } on http.ClientException catch (e) { throw Exception('Koneksi gagal: ${e.message}'); } } void close() => _http.close(); }