Skip to content

Commit

Permalink
feat: 831 - Prices getLocation, getPriceProduct, getStatus methods (#855
Browse files Browse the repository at this point in the history
)

New files:
* `location.dart`: Location object in the Prices API.
* `location.g.dart`: generated
* `price_product.dart`: Product object in the Prices API.
* `price_product.g.dart`: generated

Impacted files:
* `api_prices_test.dart`: added tests for `getLocation`, `getPriceProduct` and `getStatus`
* `open_prices_api_client.dart`: new methods `getLocation`, `getPriceProduct` and `getStatus`
* `openfoodfacts.dart`: exported the 2 new files
* `price.dart`: minor refactoring
* `price.g.dart`: generated
  • Loading branch information
monsieurtanuki authored Feb 13, 2024
1 parent 34d68bf commit e18080b
Show file tree
Hide file tree
Showing 9 changed files with 298 additions and 26 deletions.
2 changes: 2 additions & 0 deletions lib/openfoodfacts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ export 'src/personalized_search/product_preferences_selection.dart';
export 'src/prices/currency.dart';
export 'src/prices/get_prices_result.dart';
export 'src/prices/get_prices_results.dart';
export 'src/prices/location.dart';
export 'src/prices/location_osm_type.dart';
export 'src/prices/price.dart';
export 'src/prices/price_product.dart';
export 'src/prices/validation_error.dart';
export 'src/prices/validation_errors.dart';
export 'src/search/autocomplete_search_result.dart';
Expand Down
63 changes: 62 additions & 1 deletion lib/src/open_prices_api_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import 'package:http/http.dart';

import 'prices/get_prices_result.dart';
import 'prices/get_prices_results.dart';
import 'prices/location.dart';
import 'prices/price_product.dart';
import 'prices/validation_errors.dart';
import 'utils/http_helper.dart';
import 'utils/open_food_api_configuration.dart';
Expand All @@ -18,7 +20,7 @@ class OpenPricesAPIClient {
static String _getHost(final UriProductHelper uriHelper) =>
uriHelper.getHost(_subdomain);

/// cf. https://prices.openfoodfacts.net/docs#/default/get_price_api_v1_prices_get
/// cf. https://prices.openfoodfacts.org/docs#/default/get_price_api_v1_prices_get
static Future<GetPricesResults> getPrices({
// TODO(monsieurtanuki): add all parameters
final int? pageSize,
Expand All @@ -43,4 +45,63 @@ class OpenPricesAPIClient {
}
return GetPricesResults.error(ValidationErrors.fromJson(decodedResponse));
}

/// cf. https://prices.openfoodfacts.org/docs#/default/get_location_api_v1_locations__location_id__get
static Future<Location?> getLocation(
final int locationId, {
final UriProductHelper uriHelper = uriHelperFoodProd,
}) async {
final Uri uri = uriHelper.getUri(
path: '/api/v1/locations/$locationId',
forcedHost: _getHost(uriHelper),
);
final Response response = await HttpHelper().doGetRequest(
uri,
uriHelper: uriHelper,
);
dynamic decodedResponse = HttpHelper().jsonDecodeUtf8(response);
if (response.statusCode == 200) {
return Location.fromJson(decodedResponse);
}
return null;
}

/// cf. https://prices.openfoodfacts.org/docs#/default/get_product_api_v1_products__product_id__get
static Future<PriceProduct?> getPriceProduct(
final int productId, {
final UriProductHelper uriHelper = uriHelperFoodProd,
}) async {
final Uri uri = uriHelper.getUri(
path: '/api/v1/products/$productId',
forcedHost: _getHost(uriHelper),
);
final Response response = await HttpHelper().doGetRequest(
uri,
uriHelper: uriHelper,
);
dynamic decodedResponse = HttpHelper().jsonDecodeUtf8(response);
if (response.statusCode == 200) {
return PriceProduct.fromJson(decodedResponse);
}
return null;
}

/// cf. https://prices.openfoodfacts.org/docs#/default/status_endpoint_api_v1_status_get
static Future<String?> getStatus({
final UriProductHelper uriHelper = uriHelperFoodProd,
}) async {
final Uri uri = uriHelper.getUri(
path: '/api/v1/status',
forcedHost: _getHost(uriHelper),
);
final Response response = await HttpHelper().doGetRequest(
uri,
uriHelper: uriHelper,
);
dynamic decodedResponse = HttpHelper().jsonDecodeUtf8(response);
if (response.statusCode == 200) {
return decodedResponse['status'];
}
return null;
}
}
66 changes: 66 additions & 0 deletions lib/src/prices/location.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'package:json_annotation/json_annotation.dart';

import 'location_osm_type.dart';
import '../interface/json_object.dart';
import '../utils/json_helper.dart';

part 'location.g.dart';

/// Location object in the Prices API.
///
/// cf. `LocationBase` in https://prices.openfoodfacts.net/docs
@JsonSerializable()
class Location extends JsonObject {
/// ID of the location in OpenStreetMap: the store where the product was bought.
@JsonKey(name: 'osm_id')
late int osmId;

/// Type of the OpenStreetMap location object.
///
/// Stores can be represented as nodes, ways or relations in OpenStreetMap.
/// It is necessary to be able to fetch the correct information about the
/// store using the ID.
@JsonKey(name: 'osm_type')
late LocationOSMType type;

/// ID in the Prices API.
@JsonKey(name: 'id')
late int locationId;

@JsonKey(name: 'osm_name')
String? name;

@JsonKey(name: 'osm_display_name')
String? displayName;

@JsonKey(name: 'osm_address_postcode')
String? postcode;

@JsonKey(name: 'osm_address_city')
String? city;

@JsonKey(name: 'osm_address_country')
String? country;

@JsonKey(name: 'osm_lat')
double? latitude;

@JsonKey(name: 'osm_lon')
double? longitude;

/// Date when the product was bought.
@JsonKey(fromJson: JsonHelper.stringTimestampToDate)
late DateTime created;

/// Date when the product was bought.
@JsonKey(fromJson: JsonHelper.nullableStringTimestampToDate)
DateTime? updated;

Location();

factory Location.fromJson(Map<String, dynamic> json) =>
_$LocationFromJson(json);

@override
Map<String, dynamic> toJson() => _$LocationToJson(this);
}
42 changes: 42 additions & 0 deletions lib/src/prices/location.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions lib/src/prices/price.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,27 @@ class Price extends JsonObject {
/// If the price is about a barcode-less product, it must be the price per
/// kilogram or per liter.
@JsonKey()
num? price;
late num price;

/// Currency of the price.
@JsonKey()
Currency? currency;
late Currency currency;

/// ID of the location in OpenStreetMap: the store where the product was bought.
@JsonKey(name: 'location_osm_id')
int? locationOSMId;
late int locationOSMId;

/// Type of the OpenStreetMap location object.
///
/// Stores can be represented as nodes, ways or relations in OpenStreetMap.
/// It is necessary to be able to fetch the correct information about the
/// store using the ID.
@JsonKey(name: 'location_osm_type')
LocationOSMType? locationOSMType;
late LocationOSMType locationOSMType;

/// Date when the product was bought.
@JsonKey(fromJson: JsonHelper.stringTimestampToDate)
DateTime? date;
late DateTime date;

/// ID of the proof, if any.
///
Expand All @@ -77,7 +77,7 @@ class Price extends JsonObject {
int? locationId;

@JsonKey(fromJson: JsonHelper.stringTimestampToDate)
DateTime? created;
late DateTime created;

Price();

Expand Down
16 changes: 8 additions & 8 deletions lib/src/prices/price.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions lib/src/prices/price_product.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:json_annotation/json_annotation.dart';

import '../interface/json_object.dart';
import '../utils/json_helper.dart';

part 'price_product.g.dart';

/// Product object in the Prices API.
///
/// cf. `ProductBase` in https://prices.openfoodfacts.net/docs
@JsonSerializable()
class PriceProduct extends JsonObject {
@JsonKey()
late String code;

@JsonKey(name: 'id')
late int productId;

@JsonKey()
String? source;

@JsonKey(name: 'product_name')
String? name;

@JsonKey(name: 'product_quantity')
int? quantity;

@JsonKey(name: 'image_url')
String? imageURL;

@JsonKey(fromJson: JsonHelper.stringTimestampToDate)
late DateTime created;

@JsonKey(fromJson: JsonHelper.nullableStringTimestampToDate)
DateTime? updated;

PriceProduct();

factory PriceProduct.fromJson(Map<String, dynamic> json) =>
_$PriceProductFromJson(json);

@override
Map<String, dynamic> toJson() => _$PriceProductToJson(this);
}
29 changes: 29 additions & 0 deletions lib/src/prices/price_product.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit e18080b

Please sign in to comment.