159 lines
4.2 KiB
Dart
159 lines
4.2 KiB
Dart
import 'package:odoo_rpc/odoo_rpc.dart';
|
|
import 'config.dart';
|
|
|
|
class OdooService {
|
|
static final OdooService _instance = OdooService._internal();
|
|
factory OdooService() => _instance;
|
|
OdooService._internal();
|
|
|
|
OdooClient? client;
|
|
|
|
void connect(String url, {OdooSession? session}) {
|
|
client = OdooClient(url, sessionId: session);
|
|
}
|
|
|
|
/// Returns the session cookie header value for authenticated image loading.
|
|
/// Usage: Image.network(url, headers: {'Cookie': OdooService().sessionCookie})
|
|
String get sessionCookie {
|
|
final sessionId = client?.sessionId?.id ?? '';
|
|
return 'session_id=$sessionId';
|
|
}
|
|
|
|
/// Returns the URL for the full notification image.
|
|
String notificationImageUrl(int notifId) =>
|
|
'${AppConfig.odooUrl}/web/image/mapan.app.notification/$notifId/image';
|
|
|
|
Future<OdooSession> login(String db, String username, String password) async {
|
|
if (client == null) throw Exception("Connect to Odoo first");
|
|
return await client!.authenticate(db, username, password);
|
|
}
|
|
|
|
Future<List<dynamic>> getLoyaltyCards(int partnerId) async {
|
|
if (client == null) throw Exception("Connect to Odoo first");
|
|
|
|
return await client!.callKw({
|
|
'model': 'loyalty.card',
|
|
'method': 'search_read',
|
|
'args': [
|
|
[['partner_id', '=', partnerId]],
|
|
],
|
|
'kwargs': {'fields': ['points', 'program_id', 'code']}
|
|
}) as List<dynamic>;
|
|
}
|
|
|
|
Future<dynamic> sendOtp({
|
|
String? email,
|
|
String? phone,
|
|
String? phoneOrEmail,
|
|
required String type,
|
|
}) async {
|
|
if (client == null) throw Exception("Connect to Odoo first");
|
|
return await client!.callRPC(
|
|
'/api/loyalty/send_otp',
|
|
'call',
|
|
{
|
|
if (email != null) 'email': email,
|
|
if (phone != null) 'phone': phone,
|
|
if (phoneOrEmail != null) 'phone_or_email': phoneOrEmail,
|
|
'type': type,
|
|
},
|
|
);
|
|
}
|
|
|
|
Future<dynamic> signUpMember({
|
|
required String name,
|
|
required String phone,
|
|
required String email,
|
|
required String birthDate,
|
|
required String gender,
|
|
required String password,
|
|
required String otp,
|
|
}) async {
|
|
if (client == null) throw Exception("Connect to Odoo first");
|
|
return await client!.callRPC(
|
|
'/api/loyalty/signup_member',
|
|
'call',
|
|
{
|
|
'name': name,
|
|
'phone': phone,
|
|
'email': email,
|
|
'birth_date': birthDate,
|
|
'gender': gender,
|
|
'password': password,
|
|
'otp': otp,
|
|
},
|
|
);
|
|
}
|
|
|
|
Future<dynamic> activateAccount({
|
|
required String phone,
|
|
required String email,
|
|
required String birthDate,
|
|
required String password,
|
|
required String otp,
|
|
}) async {
|
|
if (client == null) throw Exception("Connect to Odoo first");
|
|
return await client!.callRPC(
|
|
'/api/loyalty/activate_account',
|
|
'call',
|
|
{
|
|
'phone': phone,
|
|
'email': email,
|
|
'birth_date': birthDate,
|
|
'password': password,
|
|
'otp': otp,
|
|
},
|
|
);
|
|
}
|
|
|
|
Future<dynamic> resetPassword({
|
|
required String phoneOrEmail,
|
|
required String otp,
|
|
required String password,
|
|
}) async {
|
|
if (client == null) throw Exception("Connect to Odoo first");
|
|
return await client!.callRPC(
|
|
'/api/loyalty/reset_password',
|
|
'call',
|
|
{
|
|
'phone_or_email': phoneOrEmail,
|
|
'otp': otp,
|
|
'password': password,
|
|
},
|
|
);
|
|
}
|
|
|
|
Future<dynamic> deleteAccount(String password) async {
|
|
if (client == null) throw Exception("Connect to Odoo first");
|
|
return await client!.callRPC(
|
|
'/api/loyalty/delete_account',
|
|
'call',
|
|
{
|
|
'password': password,
|
|
},
|
|
);
|
|
}
|
|
|
|
/// Fetch public branch information using our secure Odoo endpoint
|
|
/// This completely isolates the Admin API Key from the Flutter Source Code!
|
|
static Future<List<dynamic>> getPublicBranches() async {
|
|
final tempClient = OdooClient(AppConfig.odooUrl);
|
|
try {
|
|
final res = await tempClient.callRPC(
|
|
'/api/loyalty/branches',
|
|
'call',
|
|
{}
|
|
);
|
|
if (res != null && res['status'] == 'success') {
|
|
return res['data'] as List<dynamic>;
|
|
} else {
|
|
throw Exception(res?['message'] ?? 'Failed to load branches');
|
|
}
|
|
} catch (e) {
|
|
rethrow;
|
|
} finally {
|
|
tempClient.close();
|
|
}
|
|
}
|
|
}
|