Skip to content

Commit

Permalink
Merge pull request #297 from AlexTelon/feature/#288-Adapt-code-to-bac…
Browse files Browse the repository at this point in the history
…kend-incoming-changes

Implemented new transaction functionality
  • Loading branch information
reeshy committed Oct 12, 2023
2 parents 0ca3010 + 1322bd4 commit 1dba8dc
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 92 deletions.
83 changes: 83 additions & 0 deletions lib/models/transaction.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/// The class is a model for a transaction. It has a bunch of properties,
/// and a constructor that takes a map of strings and dynamic values
class Transaction {
String klarnaClientToken = "";
String klarnaSessionID = "";
int transactionID = -1;
int startTimestamp = -1;
int kwhTransferred = -1;
int currentChargePercentage = -1;
int pricePerKwh = -1;
int connectorID = -1;
String userID = "";
int price = -1;
int endTimeStamp = -1;
int discount = -1;

Transaction();

@override
String toString() {
return 'Transaction ID: $transactionID startTimeStamp: $startTimestamp endTimeStamp: $endTimeStamp';
}

/// The function `updateFrom` updates the current object's properties with the corresponding properties
/// from another `Transaction` object if they are not empty or have a specific value.
///
/// Args:
/// other (Transaction): The "other" parameter is an instance of the Transaction class that contains
/// the updated values for the transaction attributes.
void updateFrom(Transaction other) {
if (other.klarnaClientToken != "") {
klarnaClientToken = other.klarnaClientToken;
}
if (other.klarnaSessionID != "") {
klarnaSessionID = other.klarnaSessionID;
}
if (other.transactionID != -1) {
transactionID = other.transactionID;
}
if (other.startTimestamp != -1) {
startTimestamp = other.startTimestamp;
}
if (other.kwhTransferred != -1) {
kwhTransferred = other.kwhTransferred;
}
if (other.currentChargePercentage != -1) {
currentChargePercentage = other.currentChargePercentage;
}
if (other.pricePerKwh != -1) {
pricePerKwh = other.pricePerKwh;
}
if (other.connectorID != -1) {
connectorID = other.connectorID;
}
if (other.userID != "") {
userID = other.userID;
}
if (other.price != -1) {
price = other.price;
}
if (other.endTimeStamp != -1) {
endTimeStamp = other.endTimeStamp;
}
if (other.discount != -1) {
discount = other.discount;
}
}

Transaction.fromJson(Map<String, dynamic> json) {
transactionID = json['transactionID'] ?? 0;
klarnaClientToken = json['klarnaClientToken'] ?? "";
klarnaSessionID = json['klarnaSessionID'] ?? "";
startTimestamp = json['startTimestamp'] ?? 0;
kwhTransferred = json['kwhTransferred'] ?? 0;
currentChargePercentage = json['currentChargePercentage'] ?? 0;
pricePerKwh = json['pricePerKWh'] ?? 0;
connectorID = json['connectorID'] ?? 0;
userID = json['userID'] ?? "";
price = json['price'] ?? 0;
endTimeStamp = json['endTimestamp'] ?? -1;
discount = json['discount'] ?? 0;
}
}
4 changes: 2 additions & 2 deletions lib/services/local_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'dart:async';
import 'package:flexicharge/enums/event_type.dart';
import 'package:flexicharge/models/charger.dart';
import 'package:flexicharge/models/charger_point.dart';
import 'package:flexicharge/models/old_transaction.dart';
import 'package:flexicharge/models/transaction.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

/// It's a class that holds data that is used by the app
Expand All @@ -13,7 +13,7 @@ class LocalData {
List<ChargerPoint> chargerPoints = [];
LatLng userLocation = LatLng(0, 0);
int chargingCharger = -1;
OldTransaction transactionSession = OldTransaction();
Transaction transactionSession = Transaction();
bool isButtonActive = true;
int chargingPercentage = 0;
//late Timer timer; This is commented out because a temporary
Expand Down
89 changes: 57 additions & 32 deletions lib/services/transaction_api_service.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import 'dart:convert';
import 'package:flexicharge/enums/error_codes.dart';
import 'package:flexicharge/models/api.dart';
import 'package:flexicharge/models/old_transaction.dart';
import 'package:flexicharge/models/transaction.dart';
import 'package:flexicharge/models/user_secure_storage.dart';
import 'package:http/http.dart' as http;

/// It's a class that makes requests to the server and returns a Transaction object
Expand All @@ -16,13 +17,21 @@ class TransactionApiService {
///
/// Returns:
/// A Future<Transaction>
Future<OldTransaction> getTransactionById(int id) async {
var response = await client.get(Uri.parse('${API.url}/transactions/$id'));
Future<Transaction> getTransactionById(int id) async {
String? accessToken = await UserSecureStorage.getUserAccessToken();

var response = await client.get(
Uri.parse('${API.url}/transaction/$id'),
headers: {
...API.defaultRequestHeaders,
'Authorization': 'Bearer $accessToken'
},
);

switch (response.statusCode) {
case 200:
var parsedTransaction = json.decode(response.body);
var transactionFromJson = OldTransaction.fromJson(parsedTransaction);
var transactionFromJson = Transaction.fromJson(parsedTransaction);
return transactionFromJson;
case 404:
throw Exception(ErrorCodes.notFound);
Expand All @@ -41,16 +50,16 @@ class TransactionApiService {
///
/// Returns:
/// A list of transactions.
Future<List<OldTransaction>> getTransactionsByUserId(int id) async {
var transactions = <OldTransaction>[];
Future<List<Transaction>> getTransactionsByUserId(int id) async {
var transactions = <Transaction>[];
var response = await client
.get(Uri.parse('${API.url}/transactions/userTransactions/$id'));

switch (response.statusCode) {
case 200:
var parsedTransactions = json.decode(response.body) as List<dynamic>;
for (var trans in parsedTransactions) {
transactions.add(OldTransaction.fromJson(trans));
transactions.add(Transaction.fromJson(trans));
}
return transactions;
case 404:
Expand All @@ -70,16 +79,16 @@ class TransactionApiService {
///
/// Returns:
/// A list of transactions.
Future<List<OldTransaction>> getTransactionsByChargerId(int id) async {
var transactions = <OldTransaction>[];
Future<List<Transaction>> getTransactionsByChargerId(int id) async {
var transactions = <Transaction>[];
var response = await client
.get(Uri.parse('${API.url}/transactions/chargerTransactions/$id'));

switch (response.statusCode) {
case 200:
var parsedTransactions = json.decode(response.body) as List<dynamic>;
for (var trans in parsedTransactions) {
transactions.add(OldTransaction.fromJson(trans));
transactions.add(Transaction.fromJson(trans));
}
return transactions;
case 404:
Expand Down Expand Up @@ -160,21 +169,23 @@ class TransactionApiService {
///
/// Returns:
/// The response is a JSON object containing the following:
Future<OldTransaction> createKlarnaPaymentSession(
Future<Transaction> createKlarnaPaymentSession(
int? userId, int chargerId) async {
var response = await client.post(Uri.parse('${API.url}/transactions'),
headers: API.defaultRequestHeaders,
String? accessToken = await UserSecureStorage.getUserAccessToken();
var response = await client.post(Uri.parse('${API.url}/transaction'),
headers: {
...API.defaultRequestHeaders,
'Authorization': 'Bearer $accessToken'
},
encoding: Encoding.getByName('utf-8'),
//These parameters do not appear to make a difference
//since the functionality on the backend is not implemented.
body: json.encode(<String, dynamic>{
'chargerID': chargerId,
'isKlarnaPayment': true
'connectorID': chargerId,
'paymentType': "klarna"
}));
switch (response.statusCode) {
case 201:
var transaction = json.decode(response.body) as Map<String, dynamic>;
var parsedSession = OldTransaction.fromJson(transaction);
var parsedSession = Transaction.fromJson(transaction);
return parsedSession;
case 400:
throw Exception(ErrorCodes.badRequest);
Expand All @@ -189,26 +200,31 @@ class TransactionApiService {

/// The request returns the updated transaction object,
/// If everything goes as expected, it will contain a paymentId.
Future<OldTransaction> createKlarnaOrder(
Future<Transaction> createKlarnaOrder(
int transactionId,
String authToken,
) async {
String? accessToken = await UserSecureStorage.getUserAccessToken();
var response = await client.put(
Uri.parse('${API.url}/transactions/start/$transactionId'),
headers: API.defaultRequestHeaders,
Uri.parse('${API.url}/transaction/start/$transactionId'),
headers: {
...API.defaultRequestHeaders,
'Authorization': 'Bearer $accessToken'
},
body: jsonEncode(<String, dynamic>{
'transactionID': transactionId,
'authorization_token': authToken
}));

switch (response.statusCode) {
case 200:
print(response.body);
var transaction = json.decode(response.body) as Map<String, dynamic>;
if (transaction.isEmpty) throw Exception(ErrorCodes.emptyResponse);
var parsedSession = OldTransaction.fromJson(transaction);
var parsedSession = Transaction.fromJson(transaction);

print("Klarna updatedSession paymentID: " +
parsedSession.paymentID.toString());
parsedSession.klarnaSessionID.toString());
return parsedSession;
case 400:
print(response.body);
Expand All @@ -226,19 +242,28 @@ class TransactionApiService {

/// The request will return an updated transaction object which contains
/// paymentConfirmed == true.
Future<OldTransaction> stopCharging(int transactionId) async {
Future<Transaction> stopCharging(int transactionId) async {
String? accessToken = await UserSecureStorage.getUserAccessToken();

var response = await client.put(
Uri.parse('${API.url}/transactions/stop/$transactionId'),
headers: API.defaultRequestHeaders);
Uri.parse('${API.url}/transaction/stop/$transactionId'),
headers: {
...API.defaultRequestHeaders,
'Authorization': 'Bearer $accessToken'
},
);

print("==============================================" +
response.statusCode.toString());
print(response.statusCode);

switch (response.statusCode) {
case 200:
// We get a List with a single Transaction object in response
var list = json.decode(response.body) as List<dynamic>;
if (list.isEmpty) throw Exception(ErrorCodes.emptyResponse);
var parsedSession = OldTransaction.fromJson(list.first);
print("Klarna updatedSession paymentConfirmed : " +
parsedSession.paymentConfirmed.toString());
var decodedRespBody = json.decode(response.body);
print("=====================================");
print(decodedRespBody);
if (decodedRespBody.isEmpty) throw Exception(ErrorCodes.emptyResponse);
var parsedSession = Transaction.fromJson(decodedRespBody);
return parsedSession;
case 400:
throw Exception(ErrorCodes.badRequest);
Expand Down
4 changes: 2 additions & 2 deletions lib/ui/screens/home_page/home_viewmodel.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'dart:async';
import 'package:flexicharge/models/old_transaction.dart';
import 'package:flexicharge/models/transaction.dart';
import 'package:flexicharge/services/transaction_api_service.dart';
import 'package:flexicharge/app/app.router.dart';
import 'package:flexicharge/models/charger_point.dart';
Expand Down Expand Up @@ -121,7 +121,7 @@ class HomeViewModel extends BaseViewModel {
/// The current charging percentage of the car.
Future<int> fetchChargingPercentage() async {
try {
OldTransaction currentTransaction = await _transactionAPI
Transaction currentTransaction = await _transactionAPI
.getTransactionById(localData.transactionSession.transactionID);

int currentChargingPercentage =
Expand Down
33 changes: 12 additions & 21 deletions lib/ui/sheets/map_bottom_sheet/snappingcheet_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'dart:async';
import 'package:flexicharge/app/app.locator.dart';
import 'package:flexicharge/models/charger.dart';
import 'package:flexicharge/models/charger_point.dart';
import 'package:flexicharge/models/old_transaction.dart';
import 'package:flexicharge/models/transaction.dart';
import 'package:flexicharge/services/charger_api_service.dart';
import 'package:flexicharge/services/local_data.dart';
import 'package:flexicharge/services/transaction_api_service.dart';
Expand Down Expand Up @@ -255,13 +255,13 @@ class CustomSnappingSheetViewModel extends BaseViewModel {
print("starting the session..");
// Create a transaction session
print("Trying to create a transaction session... ");
OldTransaction transactionSession =
Transaction transactionSession =
await _transactionAPI.createKlarnaPaymentSession(null, id);
localData.transactionSession = transactionSession;
print("TransactionID: " +
localData.transactionSession.transactionID.toString());
print("clientToken: " +
localData.transactionSession.clientToken.toString());
localData.transactionSession.klarnaClientToken.toString());

print('Done');

Expand All @@ -270,7 +270,7 @@ class CustomSnappingSheetViewModel extends BaseViewModel {
print("Getting auth token...");

String authToken =
await _startKlarnaActivity(transactionSession.clientToken);
await _startKlarnaActivity(transactionSession.klarnaClientToken);
print("authToken: " + authToken);

print("auth token: " + authToken);
Expand All @@ -284,21 +284,12 @@ class CustomSnappingSheetViewModel extends BaseViewModel {
await _transactionAPI.createKlarnaOrder(
transactionSession.transactionID, authToken);

int numberOfCalls = 100;
// Start the loop
for (int i = 0; i < numberOfCalls; i++) {
// Calculate the delay for each call
Duration delay = Duration(seconds: i * 3);
Transaction specificTransaction = await _transactionAPI
.getTransactionById(transactionSession.transactionID);
localData.transactionSession.updateFrom(specificTransaction);

// Schedule the call after the delay
Timer(delay, () async {
localData.transactionSession = await _transactionAPI
.getTransactionById(transactionSession.transactionID);
});
}

print(
"payment ID" + localData.transactionSession.paymentID.toString());
print("payment ID" +
localData.transactionSession.klarnaSessionID.toString());
}
} catch (e) {
print(e);
Expand All @@ -312,10 +303,10 @@ class CustomSnappingSheetViewModel extends BaseViewModel {
try {
// Reserve charger during payment
print("trying to disconnect the charger...");
localData.transactionSession = await _transactionAPI.stopCharging(id);
Transaction stoppedChargingSession =
await _transactionAPI.stopCharging(id);
localData.transactionSession.updateFrom(stoppedChargingSession);
print("charger is disconnected");
print("paymentConfirmed: " +
localData.transactionSession.paymentConfirmed.toString());
} catch (e) {
print(e);
}
Expand Down
Loading

0 comments on commit 1dba8dc

Please sign in to comment.