209 lines
6.7 KiB
Dart
209 lines
6.7 KiB
Dart
/// Address Remote Data Source
|
|
///
|
|
/// Handles API calls to Frappe ERPNext address endpoints.
|
|
library;
|
|
|
|
import 'package:dio/dio.dart';
|
|
import 'package:worker/core/errors/exceptions.dart';
|
|
import 'package:worker/features/account/data/models/address_model.dart';
|
|
|
|
/// Address Remote Data Source
|
|
///
|
|
/// Provides methods to interact with address API endpoints.
|
|
/// Online-only approach - no offline caching.
|
|
class AddressRemoteDataSource {
|
|
final Dio _dio;
|
|
|
|
AddressRemoteDataSource(this._dio);
|
|
|
|
/// Get list of addresses
|
|
///
|
|
/// Fetches all addresses for the authenticated user.
|
|
/// Optionally filter by default address.
|
|
///
|
|
/// API: GET /api/method/building_material.building_material.api.address.get_list
|
|
Future<List<AddressModel>> getAddresses({
|
|
int limitStart = 0,
|
|
int limitPageLength = 0,
|
|
bool? isDefault,
|
|
}) async {
|
|
try {
|
|
_debugPrint('Fetching addresses list...');
|
|
|
|
final response = await _dio.post(
|
|
'/api/method/building_material.building_material.api.address.get_list',
|
|
data: {
|
|
'limit_start': limitStart,
|
|
'limit_page_length': limitPageLength,
|
|
if (isDefault != null) 'is_default': isDefault,
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = response.data;
|
|
_debugPrint('Response data: $data');
|
|
|
|
// Extract addresses from response
|
|
if (data is Map<String, dynamic> && data.containsKey('message')) {
|
|
final message = data['message'];
|
|
_debugPrint('Message type: ${message.runtimeType}');
|
|
|
|
// Handle array response
|
|
if (message is List) {
|
|
_debugPrint('Parsing ${message.length} addresses from list');
|
|
final addresses = <AddressModel>[];
|
|
for (var i = 0; i < message.length; i++) {
|
|
try {
|
|
final item = message[i] as Map<String, dynamic>;
|
|
_debugPrint('Parsing address $i: $item');
|
|
final address = AddressModel.fromJson(item);
|
|
addresses.add(address);
|
|
} catch (e) {
|
|
_debugPrint('Error parsing address $i: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
_debugPrint('Fetched ${addresses.length} addresses');
|
|
return addresses;
|
|
}
|
|
|
|
// Handle object with data field
|
|
if (message is Map<String, dynamic> && message.containsKey('data')) {
|
|
final dataList = message['data'] as List;
|
|
_debugPrint('Parsing ${dataList.length} addresses from data field');
|
|
final addresses = <AddressModel>[];
|
|
for (var i = 0; i < dataList.length; i++) {
|
|
try {
|
|
final item = dataList[i] as Map<String, dynamic>;
|
|
_debugPrint('Parsing address $i: $item');
|
|
final address = AddressModel.fromJson(item);
|
|
addresses.add(address);
|
|
} catch (e) {
|
|
_debugPrint('Error parsing address $i: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
_debugPrint('Fetched ${addresses.length} addresses');
|
|
return addresses;
|
|
}
|
|
}
|
|
|
|
throw const ServerException('Invalid response format');
|
|
} else {
|
|
throw ServerException(
|
|
'Failed to fetch addresses: ${response.statusCode}',
|
|
);
|
|
}
|
|
} catch (e) {
|
|
_debugPrint('Error fetching addresses: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Create or update address
|
|
///
|
|
/// If name is provided (not empty), updates existing address.
|
|
/// If name is null/empty, creates new address.
|
|
///
|
|
/// Per API docs: When name field is null/empty, the API creates a new address.
|
|
/// When name has a value, the API updates the existing address.
|
|
///
|
|
/// API: POST /api/method/building_material.building_material.api.address.update
|
|
Future<AddressModel> saveAddress(AddressModel address) async {
|
|
try {
|
|
final isUpdate = address.name.isNotEmpty;
|
|
_debugPrint(
|
|
isUpdate
|
|
? 'Updating address: ${address.name}'
|
|
: 'Creating new address',
|
|
);
|
|
|
|
// toJson() already handles setting name to null for creation
|
|
final data = address.toJson();
|
|
_debugPrint('Request data: $data');
|
|
|
|
final response = await _dio.post(
|
|
'/api/method/building_material.building_material.api.address.update',
|
|
data: data,
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = response.data;
|
|
_debugPrint('Response data: $data');
|
|
|
|
// Check for API error response (even with 200 status)
|
|
if (data is Map<String, dynamic> && data.containsKey('message')) {
|
|
final message = data['message'];
|
|
|
|
// Check for error response format
|
|
if (message is Map<String, dynamic> && message.containsKey('error')) {
|
|
final error = message['error'] as String;
|
|
_debugPrint('API error: $error');
|
|
throw ServerException(error);
|
|
}
|
|
|
|
// Handle direct address object
|
|
if (message is Map<String, dynamic>) {
|
|
final savedAddress = AddressModel.fromJson(message);
|
|
_debugPrint('Address saved: ${savedAddress.name}');
|
|
return savedAddress;
|
|
}
|
|
|
|
// Handle nested data
|
|
if (message is Map<String, dynamic> && message.containsKey('data')) {
|
|
final savedAddress =
|
|
AddressModel.fromJson(message['data'] as Map<String, dynamic>);
|
|
_debugPrint('Address saved: ${savedAddress.name}');
|
|
return savedAddress;
|
|
}
|
|
}
|
|
|
|
throw const ServerException('Invalid response format');
|
|
} else {
|
|
throw ServerException(
|
|
'Failed to save address: ${response.statusCode}',
|
|
);
|
|
}
|
|
} catch (e) {
|
|
_debugPrint('Error saving address: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Delete address
|
|
///
|
|
/// Note: API endpoint for delete not provided in docs.
|
|
/// This is a placeholder - adjust when endpoint is available.
|
|
Future<void> deleteAddress(String name) async {
|
|
try {
|
|
_debugPrint('Deleting address: $name');
|
|
|
|
// TODO: Update with actual delete endpoint when available
|
|
final response = await _dio.post(
|
|
'/api/method/building_material.building_material.api.address.delete',
|
|
data: {'name': name},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
_debugPrint('Address deleted: $name');
|
|
return;
|
|
} else {
|
|
throw ServerException(
|
|
'Failed to delete address: ${response.statusCode}',
|
|
);
|
|
}
|
|
} catch (e) {
|
|
_debugPrint('Error deleting address: $e');
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Debug print helper
|
|
void _debugPrint(String message) {
|
|
// ignore: avoid_print
|
|
print('[AddressRemoteDataSource] $message');
|
|
}
|
|
}
|