Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 831 - Prices getLocation, getPriceProduct, getStatus methods #855

Merged
merged 9 commits into from
Feb 13, 2024
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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you renamed latitude/longitude, I would rename it to createDate


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

@g123k g123k Dec 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you renamed latitude/longitude, I would rename it to updatedDate


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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By curiosity, why don't you include JsonKeys in this file?


/// 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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same suggestion as before


@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
Loading