diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index f60ca9c..5d85022 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -90,6 +90,8 @@ dependencies {
implementation(libs.material)
implementation(libs.constraintlayout)
+ implementation(libs.printerlibrary)
+
implementation(libs.navigation.fragment)
implementation(libs.navigation.ui)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c6c6ad2..55ff5dd 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -16,6 +16,11 @@
+
+
+
+
+
@@ -40,6 +45,10 @@
+
+
+
+
{
String reference = binding.referenceTicket.getText().toString();
if(reference.isEmpty()){
- Toast.makeText(getContext(),"Entrez la référence du ticket", Toast.LENGTH_SHORT).show();
+ MessageDialog.showError(getContext(), "Veuillez donner la reference du ticket");
return;
}
- viewModel.annulerPari(reference).observe(getViewLifecycleOwner(), new Observer>() {
+ viewModel.getPariByNumero(reference).observe(getViewLifecycleOwner(), new Observer>() {
@Override
- public void onChanged(Result pariResult) {
- switch (pariResult.status){
- case LOADING:{
- dialog.show("Annulation du ticket");
- break;
- }
- case ERROR:{
- dialog.dismiss();
- MessageDialog.showError(getContext(), pariResult.message);
- break;
- }
- case SUCCESS:{
- dialog.dismiss();
- MessageDialog.showSuccess(getContext(), "Ticket annulé avec succès");
- logsViewModel.insertLog(prefsHelper.get("id"), "ANNULATION TICKET", "Annulation du ticket "+pariResult.data.getNumeroTicket(), System.currentTimeMillis());
- binding.referenceTicket.setText("");
- }
- }
+ public void onChanged(Result parisResponseResult) {
+ switch (parisResponseResult.status){
+ case LOADING:{
+ dialog.show("Recherche du ticket");
+ break;
+ }
+ case ERROR:{
+ MessageDialog.showError(getContext(), parisResponseResult.message);
+ break;
+ }
+ case SUCCESS:{
+ if(parisResponseResult.data.getNumeroTicket().equals(reference)){
+ dialog.dismiss();
+ if(parisResponseResult.data.getStatutPari() == ParisResponse.StatutPari.ANNULE){
+ MessageDialog.showError(getContext(), "Le ticket est déjà annulé");
+ return;
+ }
+ _showPariDialog(reference);
+ }else{
+ MessageDialog.showError(getContext(), "Le ticket n'existe pas");
+ }
+ }
+ }
}
});
});
}
+ void _showPariDialog(String ticketReference){
+ new AlertDialog.Builder(getContext())
+ .setTitle("Annulation du ticket")
+ .setMessage("Etes-vous sûr de vouloir annuler le ticket "+ticketReference+" ?")
+ .setCancelable(true)
+ .setNegativeButton("Annuler", (dialog, which) -> {
+ dialog.dismiss();
+ })
+ .setPositiveButton("Confirmer", (annulationDialog, which) -> {
+ viewModel.annulerPari(ticketReference).observe(getViewLifecycleOwner(), new Observer>() {
+ @Override
+ public void onChanged(Result pariResult) {
+ switch (pariResult.status){
+ case LOADING:{
+ dialog.show("Annulation du ticket");
+ break;
+ }
+ case ERROR:{
+ dialog.dismiss();
+ MessageDialog.showError(getContext(), pariResult.message);
+ break;
+ }
+ case SUCCESS:{
+ dialog.dismiss();
+ MessageDialog.showSuccess(getContext(), "Ticket annulé avec succès");
+ logsViewModel.insertLog(prefsHelper.get("id"), "ANNULATION TICKET", "Annulation du ticket "+pariResult.data.getNumeroTicket(), System.currentTimeMillis());
+ binding.referenceTicket.setText("");
+ }
+ }
+ }
+ });
+ }).show();
+ }
+
@Override
public void onResume() {
super.onResume();
diff --git a/app/src/main/java/com/example/quiz/BetValidation.java b/app/src/main/java/com/example/quiz/BetValidation.java
index 2c8d5c9..a4caec2 100644
--- a/app/src/main/java/com/example/quiz/BetValidation.java
+++ b/app/src/main/java/com/example/quiz/BetValidation.java
@@ -1,14 +1,19 @@
package com.example.quiz;
-import android.Manifest;
+
import android.annotation.SuppressLint;
-import android.bluetooth.BluetoothAdapter;
+import android.app.Dialog;
import android.content.Intent;
-import android.content.pm.PackageManager;
+
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
+import android.os.Build;
import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher;
@@ -16,10 +21,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
@@ -42,11 +44,9 @@ import com.example.quiz.data.model.MiseInitiale;
import com.example.quiz.data.model.Pari;
import com.example.quiz.data.model.PariMise;
import com.example.quiz.data.model.ParisResponse;
-import com.example.quiz.data.model.Reunion;
+
import com.example.quiz.data.model.TypeOfBet;
import com.example.quiz.data.model.dtos.NotifPayload;
-import com.example.quiz.data.model.dtos.PariCourseDto;
-import com.example.quiz.data.model.enums.PariStatut;
import com.example.quiz.data.remote.StompManager;
import com.example.quiz.databinding.FragmentBetValidationBinding;
import com.example.quiz.utils.BluetoothUtils;
@@ -54,6 +54,7 @@ import com.example.quiz.utils.LoaderDialog;
import com.example.quiz.utils.MessageDialog;
import com.example.quiz.utils.Result;
import com.example.quiz.utils.SharedPrefsHelper;
+import com.example.quiz.utils.SunmiPrinterManager;
import com.example.quiz.viewModel.LogsViewModel;
import com.example.quiz.viewModel.PariMiseViewModel;
import com.example.quiz.viewModel.PariViewModel;
@@ -67,15 +68,17 @@ import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import java.lang.reflect.Type;
-import java.time.LocalDate;
+
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
-import java.util.Map;
+
import java.util.Objects;
+import java.util.Observable;
import java.util.stream.Collectors;
import javax.inject.Inject;
@@ -93,8 +96,10 @@ public class BetValidation extends Fragment {
FragmentBetValidationBinding binding;
+
SharedViewModel shared;
+
PariMiseViewModel pariMiseViewModel;
List misesInitiales;
@@ -104,6 +109,8 @@ public class BetValidation extends Fragment {
@Inject
StompManager stompManager;
+ SunmiPrinterManager sunmiPrinterManager;
+
private int nombreX;
LogsViewModel logsViewModel;
@@ -113,16 +120,20 @@ public class BetValidation extends Fragment {
private long mise;
+ String mobileName;
+
private TypeOfBet typeOfBet;
+ MutableLiveData isPrinterReady = new MutableLiveData<>(false);
+
SharedPrefsHelper prefsHelper;
private Course course;
- LoaderDialog loader;
+ LoaderDialog loader;
private int coeff;
@@ -135,12 +146,11 @@ public class BetValidation extends Fragment {
PariViewModel pariViewModel;
-
public BetValidation() {
// Required empty public constructor
}
- public static BetValidation newInstance() {
+ public static BetValidation newInstance() {
BetValidation fragment = new BetValidation();
Bundle args = new Bundle();
fragment.setArguments(args);
@@ -151,8 +161,16 @@ public class BetValidation extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prefsHelper = SharedPrefsHelper.getInstance(getContext());
+ mobileName = Build.MANUFACTURER;
+ sunmiPrinterManager = SunmiPrinterManager.getInstance(requireContext());
+ if(mobileName.toLowerCase().contains("sunmi")){
+ sunmiPrinterManager.connectPrinter(status ->{
+ isPrinterReady.setValue(status);
+ });
+ }
}
+
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -161,7 +179,7 @@ public class BetValidation extends Fragment {
logsViewModel = new ViewModelProvider(this).get(LogsViewModel.class);
binding.coeff.setText(String.valueOf(1));
coeff = Integer.parseInt(binding.coeff.getText().toString());
- binding.coeff.addTextChangedListener(new TextWatcher(){
+ binding.coeff.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
@@ -169,11 +187,11 @@ public class BetValidation extends Fragment {
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
- if(charSequence.toString().isEmpty()){
+ if (charSequence.toString().isEmpty()) {
binding.coeff.setError("Le coefficient est obligatoire");
return;
}
- if(Integer.parseInt(charSequence.toString())<1){
+ if (Integer.parseInt(charSequence.toString()) < 1) {
binding.coeff.setError("Le coefficient doit être supérieur ou égal à 1 ");
return;
}
@@ -194,7 +212,7 @@ public class BetValidation extends Fragment {
binding.gridNumbers.removeAllViews();
int columns = 8;
grid.setColumnCount(columns);
- if(shared.selectedCourse.getValue() != null){
+ if (shared.selectedCourse.getValue() != null) {
for (int i = 1; i <= shared.selectedCourse.getValue().getNombrePartants(); i++) {
createNumberItem(String.valueOf(i));
grid.addView(createNumberItem(String.valueOf(i)));
@@ -203,7 +221,6 @@ public class BetValidation extends Fragment {
createNumberItem("X");
grid.addView(createNumberItem("X"));
}
-
private TextView createNumberItem(String horse) {
TextView textView = new TextView(requireContext());
textView.setText(horse);
@@ -215,53 +232,53 @@ public class BetValidation extends Fragment {
textView.setWidth(80);
textView.setHeight(100);
textView.setGravity(Gravity.CENTER);
- textView.setBackgroundResource(Objects.equals(horse, "X") ?R.drawable.x_background: R.drawable.number_background);
- if(!Objects.equals(horse, "X") && shared.selectedCourse.getValue().getNonPartants() != null && shared.selectedCourse.getValue().getNonPartants().contains(Integer.valueOf(horse))){
+ textView.setBackgroundResource(Objects.equals(horse, "X") ? R.drawable.x_background : R.drawable.number_background);
+ if (!Objects.equals(horse, "X") && shared.selectedCourse.getValue().getNonPartants() != null && shared.selectedCourse.getValue().getNonPartants().contains(Integer.valueOf(horse))) {
textView.setTextColor(getResources().getColor(R.color.white));
textView.setBackgroundResource(R.drawable.number_background_grey);
}
textView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
textView.setOnClickListener(v -> {
- if(!Objects.equals(horse, "X") && shared.selectedCourse.getValue().getNonPartants() != null && shared.selectedCourse.getValue().getNonPartants().contains(Integer.valueOf(horse))){
+ if (!Objects.equals(horse, "X") && shared.selectedCourse.getValue().getNonPartants() != null && shared.selectedCourse.getValue().getNonPartants().contains(Integer.valueOf(horse))) {
Toast.makeText(getContext(), "Ce cheval n'est pas partant", Toast.LENGTH_SHORT).show();
return;
}
final List horses = new ArrayList<>(selectedHorses.getValue());
- if(horses.size() >= shared.typeOfBet.getValue().getNumberOfHorse() && horse.equals("X")){
- Toast.makeText(getContext(), "Vous ne pouvez plus sélectionner X", Toast.LENGTH_SHORT).show();
- return;
- }
- if(_notClickable(horses) && horse.equals("X")){
- Toast.makeText(getContext(), "Vous ne pouvez plus sélectionner X", Toast.LENGTH_SHORT).show();
- return;
- }
- if (horses.contains(horse) && !horse.equals("X")) {
- horses.remove(horse);
- selectedHorses.setValue(horses);
- v.setSelected(false);
- v.setBackgroundResource(R.drawable.number_background);
- } else {
- horses.add(horse);
- selectedHorses.setValue(horses);
- v.setSelected(true);
- v.setBackgroundResource(R.drawable.number_selected_background);
- }
- String combinationText = selectedHorses.getValue().stream()
- .map(h -> h)
- .collect(Collectors.joining("-"));
- binding.combination.setText( combinationText);
- });
+ if (horses.size() >= shared.typeOfBet.getValue().getNumberOfHorse() && horse.equals("X")) {
+ Toast.makeText(getContext(), "Vous ne pouvez plus sélectionner X", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (_notClickable(horses) && horse.equals("X")) {
+ Toast.makeText(getContext(), "Vous ne pouvez plus sélectionner X", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ if (horses.contains(horse) && !horse.equals("X")) {
+ horses.remove(horse);
+ selectedHorses.setValue(horses);
+ v.setSelected(false);
+ v.setBackgroundResource(R.drawable.number_background);
+ } else {
+ horses.add(horse);
+ selectedHorses.setValue(horses);
+ v.setSelected(true);
+ v.setBackgroundResource(R.drawable.number_selected_background);
+ }
+ String combinationText = selectedHorses.getValue().stream()
+ .map(h -> h)
+ .collect(Collectors.joining("-"));
+ binding.combination.setText(combinationText);
+ });
return textView;
}
- boolean _notClickable(List selectedHorses){
+ boolean _notClickable(List selectedHorses) {
int numberOfElement = 0;
- if(shared.typeOfBet.getValue().getNumberOfHorse() < 2){
+ if (shared.typeOfBet.getValue().getNumberOfHorse() < 2) {
return true;
}
- for(String horse: selectedHorses){
- numberOfElement = horse.equals("X")?numberOfElement+1:numberOfElement;
+ for (String horse : selectedHorses) {
+ numberOfElement = horse.equals("X") ? numberOfElement + 1 : numberOfElement;
}
nombreX = numberOfElement;
return numberOfElement == shared.typeOfBet.getValue().getNumberOfHorse() - 1;
@@ -274,8 +291,8 @@ public class BetValidation extends Fragment {
pariMiseViewModel = new ViewModelProvider(this).get(PariMiseViewModel.class);
pariMiseViewModel.getBetInitMise().observe(
getViewLifecycleOwner(),
- result->{
- switch (result.status){
+ result -> {
+ switch (result.status) {
case LOADING: {
loader.show("Chargement des mise");
break;
@@ -294,12 +311,13 @@ public class BetValidation extends Fragment {
}
}
);
- if(shared.selectedCourse.getValue() != null){
- stompManager.subscribe("courses/"+shared.selectedCourse.getValue().getId(), json->{
- Type type = new TypeToken>(){}.getType();
+ if (shared.selectedCourse.getValue() != null) {
+ stompManager.subscribe("courses/" + shared.selectedCourse.getValue().getId(), json -> {
+ Type type = new TypeToken>() {
+ }.getType();
NotifPayload notif = new Gson().fromJson(json, type);
Course updatedCourse = notif.getPayload();
- if(shared.selectedCourse.getValue().getId() == updatedCourse.getId()){
+ if (shared.selectedCourse.getValue().getId() == updatedCourse.getId()) {
shared.setSelectedCourse(updatedCourse);
setupNumberGrid(binding.gridNumbers);
}
@@ -310,12 +328,12 @@ public class BetValidation extends Fragment {
typeOfBet = shared.typeOfBet.getValue();
course = shared.selectedCourse.getValue();
AppCompatActivity activity = (AppCompatActivity) getActivity();
- if(activity != null){
+ if (activity != null) {
MaterialToolbar toolbar = activity.findViewById(R.id.toolbar);
- toolbar.setBackgroundColor( getResources().getColor(R.color.primary_green));
+ toolbar.setBackgroundColor(getResources().getColor(R.color.primary_green));
activity.setSupportActionBar(toolbar);
- if(activity.getSupportActionBar() != null){
- activity.getSupportActionBar().setTitle("Pari "+shared.selectedCourse.getValue().getNom());
+ if (activity.getSupportActionBar() != null) {
+ activity.getSupportActionBar().setTitle("Pari " + shared.selectedCourse.getValue().getNom());
}
}
setupNumberGrid(binding.gridNumbers);
@@ -342,28 +360,28 @@ public class BetValidation extends Fragment {
@Override
public void onChanged(List horses) {
calculateMise(horses);
- if(shared.typeOfBet.getValue().getNumberOfHorse() > 2 && horses.size() >= shared.typeOfBet.getValue().getNumberOfHorse()){
+ if (shared.typeOfBet.getValue().getNumberOfHorse() > 2 && horses.size() >= shared.typeOfBet.getValue().getNumberOfHorse()) {
binding.order.setVisibility(View.VISIBLE);
- }else{
+ } else {
binding.order.setVisibility(View.GONE);
}
- if(horses.contains("X")){
- if(selectedHorses.getValue().size() == shared.typeOfBet.getValue().getNumberOfHorse()){
+ if (horses.contains("X")) {
+ if (selectedHorses.getValue().size() == shared.typeOfBet.getValue().getNumberOfHorse()) {
binding.elargie.setVisibility(View.VISIBLE);
binding.elargie.setText("Champ total");
return;
- }else{
- if(selectedHorses.getValue().size() > shared.typeOfBet.getValue().getNumberOfHorse()){
+ } else {
+ if (selectedHorses.getValue().size() > shared.typeOfBet.getValue().getNumberOfHorse()) {
binding.elargie.setVisibility(View.VISIBLE);
binding.elargie.setText("Champ partiel");
return;
}
}
}
- if(horses.size() > shared.typeOfBet.getValue().getNumberOfHorse()){
+ if (horses.size() > shared.typeOfBet.getValue().getNumberOfHorse()) {
binding.elargie.setVisibility(View.VISIBLE);
binding.elargie.setText("Elargi");
- }else{
+ } else {
binding.elargie.setVisibility(View.GONE);
}
}
@@ -373,48 +391,24 @@ public class BetValidation extends Fragment {
calculateMise(selectedHorses.getValue());
});
- binding.betValidateBtn.setOnClickListener(v->{
-// Log.d("PAPER_STATUS", String.valueOf(ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.BLUETOOTH_CONNECT))+" "+String.valueOf(PackageManager.PERMISSION_GRANTED));
-// if (ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.BLUETOOTH_CONNECT)
-// != PackageManager.PERMISSION_GRANTED) {
-// // TODO: Consider calling
-// // ActivityCompat#requestPermissions
-// // here to request the missing permissions, and then overriding
-// // public void onRequestPermissionsResult(int requestCode, String[] permissions,
-// // int[] grantResults)
-// // to handle the case where the user grants the permission. See the documentation
-// // for ActivityCompat#requestPermissions for more details.
-// return;
-// }
-// int paperStatus = Printama.with(getContext()).checkPaperStatus();
-// switch (paperStatus){
-// case 2 :{
-// MessageDialog.showError(getContext(), "Le papier d'impression est vide");
-// return;
-// }
-// case 1:{
-// MessageDialog.showError(getContext(), "Le papier d'impression est presque vide");
-// break;
-// }
-// }
-
- if(binding.paymentType.getSelectedItem().toString().equals("Orange Money") && binding.phoneNumber.getText().toString().isEmpty()){
+ binding.betValidateBtn.setOnClickListener(v -> {
+ if (binding.paymentType.getSelectedItem().toString().equals("Orange Money") && binding.phoneNumber.getText().toString().isEmpty()) {
MessageDialog.showError(getContext(), "Veuillez saisir le numéro de téléphone");
return;
}
- if(shared.typeOfBet == null || shared.selectedCourse == null){
+ if (shared.typeOfBet == null || shared.selectedCourse == null) {
return;
}
int required = typeOfBet.getNumberOfHorse();
- if(selectedHorses.getValue().size() < required){
- Toast.makeText(getContext(), "Veuillez sélectionner au moins"+required+" chevaux", Toast.LENGTH_SHORT).show();
+ if (Objects.requireNonNull(selectedHorses.getValue()).size() < required) {
+ Toast.makeText(getContext(), "Veuillez sélectionner au moins" + required + " chevaux", Toast.LENGTH_SHORT).show();
return;
}
- if(this.mise == 0){
+ if (this.mise == 0) {
Toast.makeText(getContext(), "Pari non valide", Toast.LENGTH_SHORT).show();
return;
}
@@ -432,61 +426,63 @@ public class BetValidation extends Fragment {
"XOF",
"Pari"
);
+ if (dialog != null && dialog.isShowing()) {
+ return;
+ }
_showPariDialog(pari);
});
- binding.backBtn.setOnClickListener(v->{
+ binding.backBtn.setOnClickListener(v -> {
getActivity().onBackPressed();
});
- binding.deleteBtn.setOnClickListener(v->{
+ binding.deleteBtn.setOnClickListener(v -> {
_initializeToZero();
});
}
-
- String _getCombinaison(){
- if(selectedHorses.getValue().contains("X") && shared.typeOfBet.getValue().getNumberOfHorse() < selectedHorses.getValue().size()){
+ String _getCombinaison() {
+ if (selectedHorses.getValue().contains("X") && shared.typeOfBet.getValue().getNumberOfHorse() < selectedHorses.getValue().size()) {
String first = selectedHorses.getValue().subList(0, shared.typeOfBet.getValue().getNumberOfHorse()).stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
String last = selectedHorses.getValue().subList(shared.typeOfBet.getValue().getNumberOfHorse(), selectedHorses.getValue().size()).stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
- return first+",R,"+last;
- }else{
+ return first + ",R," + last;
+ } else {
return selectedHorses.getValue().stream().map(String::valueOf).collect(Collectors.joining(","));
}
}
- List _getFormule(){
+ List _getFormule() {
List combinaison = selectedHorses.getValue();
- if(!combinaison.contains("X")){
- if(!order){
- return List.of("UNITAIRE");
- }else{
+ if (!combinaison.contains("X")) {
+ if (!order) {
+ return List.of("UNITAIRE");
+ } else {
return List.of("FORMULE_COMPLETE");
}
- }else{
- if(shared.typeOfBet.getValue().getNumberOfHorse() < selectedHorses.getValue().size()){
- if(order){
+ } else {
+ if (shared.typeOfBet.getValue().getNumberOfHorse() < selectedHorses.getValue().size()) {
+ if (order) {
return List.of("CHAMP_X", "FORMULE_COMPLETE");
- }else{
+ } else {
return List.of("CHAMP_X");
}
- }else{
- if(order){
+ } else {
+ if (order) {
return List.of("CHAMP_TOTAL", "FORMULE_COMPLETE");
- }else{
+ } else {
return List.of("CHAMP_TOTAL");
}
}
}
}
- private void setSelectedTypeOfBetImage(){
- switch (shared.typeOfBet.getValue().getName()){
+ private void setSelectedTypeOfBetImage() {
+ switch (shared.typeOfBet.getValue().getName()) {
case COUPLE_PLACE:
binding.icTypeOfBet.setImageResource(R.drawable.ic_couple_place);
break;
@@ -506,34 +502,41 @@ public class BetValidation extends Fragment {
}
public void printPari(ParisResponse pari) throws WriterException {
- try {
- Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo);
- Bitmap barcode = generateBarcodeBitmap(pari.getNumeroTicket(), 384, 100);
- StringBuilder tspl = new StringBuilder();
- Printama printama = Printama.with(getContext());
+ Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo);
+ Bitmap barcode = generateBarcodeBitmap(pari.getNumeroTicket(), 384, 100);
+ StringBuilder tspl = new StringBuilder();
+ tspl.append("Bamako").append("\n");
+ tspl.append(shared.selectedCourse.getValue().getNom()).append("\n");
+ OffsetDateTime dateTime = OffsetDateTime.parse(shared.selectedCourse.getValue().getHeureDepartPrevue());
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
+ String formattedDate = dateTime.format(formatter);
+ tspl.append(formattedDate).append("\n");
+ tspl.append("Course ").append(String.valueOf(shared.selectedCourse.getValue().getId())).append("\n");
+ tspl.append(sunmiPrinterManager.separationText()+ "\n");
+ boolean isElargie = selectedHorses.getValue().size() > shared.typeOfBet.getValue().getNumberOfHorse();
+ String typePari = pari.getTypesParisMises().get(0).getTypePari();
+ tspl.append(isElargie ? typePari + "/Elargie" : typePari).append("\n");
+ tspl.append(order ? "COMBINAISON COMPLETE" + "\n" : "");
+ String combinationText = formatLineWithNumbers(selectedHorses.getValue().stream().map(String::valueOf).toArray(String[]::new), "-") ;
+ tspl.append(combinationText).append("\n");
+ tspl.append("COEF: ").append(String.valueOf(coeff)).append(".0");
+ tspl.append("\n").append(sunmiPrinterManager.separationText()).append("\n");
+ tspl.append("MONTANT: ").append(pari.getTypesParisMises().get(0).getMiseTotale()).append(" XOF");
+ tspl.append("\n").append(sunmiPrinterManager.separationText()).append("\n");
+ tspl.append("AGENT: ").append(prefsHelper.get("code")).append("\n");
+ tspl.append("DATE: ").append(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").format(LocalDateTime.now())).append("\n");
+ if(mobileName.toLowerCase().contains("sunmi")){
+ String pariText = tspl.toString();
+ if(!sunmiPrinterManager.printPari(resizeToPrinterWidth(bitmap, 384), barcode, pari.getNumeroTicket(), pariText)){
+ MessageDialog.showError(getContext(), "Erreur d'impression");
+ prefsHelper.save("noPrintId", String.valueOf(pari.getId()));
+ return;
+ };
+ _initializeToZero();
+ return;
+ }
- tspl.append("Bamako").append("\n");
- tspl.append(shared.selectedCourse.getValue().getNom()).append("\n");
- OffsetDateTime dateTime = OffsetDateTime.parse(shared.selectedCourse.getValue().getHeureDepartPrevue());
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
- String formattedDate = dateTime.format(formatter);
- tspl.append(formattedDate).append("\n");
- tspl.append("Course ").append(String.valueOf(shared.selectedCourse.getValue().getId())).append("\n");
- tspl.append(printama.lineSeparator()+"\n");
- boolean isElargie = selectedHorses.getValue().size()>shared.typeOfBet.getValue().getNumberOfHorse();
- String typePari = pari.getTypesParisMises().get(0).getTypePari();
- tspl.append(isElargie?typePari+"/Elargie":typePari).append("\n");
- tspl.append(order?"COMBINAISON COMPLETE"+"\n":"");
- String combinationText = selectedHorses.getValue().stream()
- .map(String::valueOf)
- .collect(Collectors.joining("-"));
- tspl.append(combinationText).append("\n");
- tspl.append("COEF: ").append(String.valueOf(coeff)).append(".0");
- tspl.append("\n").append(printama.lineSeparator()).append("\n");
- tspl.append("MONTANT: ").append(pari.getTypesParisMises().get(0).getMiseTotale()).append(" XOF");
- tspl.append("\n").append(printama.lineSeparator()).append("\n");
- tspl.append("AGENT: ").append(prefsHelper.get("code")).append("\n");
- tspl.append("DATE: ").append(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").format(LocalDateTime.now())).append("\n");
+ try {
if (BluetoothUtils.needsBluetoothPermissions()) {
if (!BluetoothUtils.hasBluetoothPermission(requireContext())) {
// Demande la permission si non accordée
@@ -544,8 +547,28 @@ public class BetValidation extends Fragment {
// 2️⃣ Permission OK, on peut afficher la liste
- Printama.with(getContext()).printTextBuilder(tspl, bitmap, pari.getNumeroTicket(), barcode);
- _initializeToZero();
+ Printama.with(getContext()).printTextBuilder(tspl, bitmap, pari.getNumeroTicket(), barcode, new Printama.PrintCallback() {
+ @Override
+ public void onResult(boolean success, String errorMessage) {
+ if (!success) {
+ new android.app.AlertDialog.Builder(getContext())
+ .setTitle("Impréssion pari")
+ .setMessage("Voulez-vous rééimprimer ce ticket?")
+ .setPositiveButton("Oui", (dialog, which) -> {
+ try {
+ printPari(pari);
+ } catch (WriterException e) {
+ throw new RuntimeException(e);
+ }
+ })
+ .setNegativeButton("Non", (dialog, which) -> {
+ dialog.dismiss();
+ });
+ } else {
+ _initializeToZero();
+ }
+ }
+ });
} catch (SecurityException e) {
Toast.makeText(requireContext(),
"Permission Bluetooth non accordée", Toast.LENGTH_SHORT).show();
@@ -553,36 +576,103 @@ public class BetValidation extends Fragment {
}
+ public String formatLineWithNumbers(String[] numbers, String separator) {
+ StringBuilder currentLine = new StringBuilder();
+ StringBuilder finalOutput = new StringBuilder();
+ List formatted = new ArrayList<>();
+ int requiredHorse = shared.typeOfBet.getValue().getNumberOfHorse();
+ if(Arrays.stream(numbers).map(String::valueOf).collect(Collectors.toList()).contains("X")){
+ if(numbers.length <= requiredHorse){
+ return Arrays.stream(numbers).map(String::valueOf).collect(Collectors.joining("-")).toString();
+ }
+ List firstPart = Arrays.stream(numbers).limit(requiredHorse).map(String::valueOf).collect(Collectors.toList());
+ List secondPart = Arrays.stream(numbers).skip(requiredHorse).map(String::valueOf).collect(Collectors.toList());
+ formatted.addAll(firstPart);
+ formatted.add("R");
+ formatted.addAll(secondPart);
+ }else{
+ formatted = Arrays.stream(numbers).map(String::valueOf).collect(Collectors.toList());
+ }
+
+ for (String number : formatted) {
+ String element = (currentLine.length() == 0 ? "":separator) + number;
+
+ // Si l'ajout dépasse la largeur max, on termine la ligne et on recommence
+ if (currentLine.length() + element.length() > sunmiPrinterManager.getMaxChar()) {
+ finalOutput.append(currentLine.toString()).append("\n");
+ currentLine = new StringBuilder(number);
+ } else {
+ currentLine.append(element);
+ }
+ }
+
+ if (currentLine.length() > 0) {
+ finalOutput.append(currentLine.toString());
+ }
+
+ return finalOutput.toString();
+ }
+
+
@SuppressLint({"MissingInflatedId", "SetTextI18n"})
- void _showPariDialog(Pari pari){
+ void _showPariDialog(Pari pari) {
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.pari_confirmation, null);
TextView numero_course = (TextView) view.findViewById(R.id.alert_course_numero);
- numero_course.setText("Numero Course: "+String.valueOf(shared.selectedCourse.getValue().getId()));
+ numero_course.setText("Numero Course: " + String.valueOf(shared.selectedCourse.getValue().getId()));
TextView alert_pari_type = (TextView) view.findViewById(R.id.alert_pari_type);
alert_pari_type.setText(String.valueOf(shared.typeOfBet.getValue().getName()));
TextView is_elargie = (TextView) view.findViewById(R.id.alert_is_elargie);
- is_elargie.setText(selectedHorses.getValue().size() > shared.typeOfBet.getValue().getNumberOfHorse()?"CE":"SI");
+ is_elargie.setText(selectedHorses.getValue().size() > shared.typeOfBet.getValue().getNumberOfHorse() ? "CE" : "SI");
TextView alert_combinaison = (TextView) view.findViewById(R.id.alert_combinaison);
alert_combinaison.setText(selectedHorses.getValue().stream()
.map(String::valueOf)
.collect(Collectors.joining("-")));
TextView aler_coeff = (TextView) view.findViewById(R.id.alert_coeff);
- aler_coeff.setText("Coef:"+String.valueOf(coeff));
+ aler_coeff.setText("Coef:" + String.valueOf(coeff));
TextView alert_montant = (TextView) view.findViewById(R.id.alert_montant);
- alert_montant.setText("Montant: "+String.valueOf(pari.getTypesParisMises().get(0).getMiseTotale())+" CFA");
+ alert_montant.setText("Montant: " + String.valueOf(pari.getTypesParisMises().get(0).getMiseTotale()) + " CFA");
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setView(view);
builder.setCancelable(false);
-
dialog = builder.create();
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
- view.findViewById(R.id.alert_validate).setOnClickListener(v->{
- pariViewModel.createPari(pari).observe(getViewLifecycleOwner(),new Observer>() {
+ view.findViewById(R.id.alert_validate).setOnClickListener(v -> {
+ if(mobileName.toLowerCase().contains("sunmi")){
+ if(isPrinterReady.getValue() != null && !isPrinterReady.getValue()){
+ sunmiPrinterManager.connectPrinter(status ->{
+ isPrinterReady.setValue(status);
+ });
+ }
+ switch (sunmiPrinterManager.printerStatus()){
+ case 2:{
+ MessageDialog.showError(getContext(), "L'imprimante n'est pas connectée!");
+ return;
+ }
+ case 3:{
+ MessageDialog.showError(getContext(), "L'imprimante n'est pas disponible!");
+ return;
+ }
+ case 4:{
+ MessageDialog.showError(getContext(), "Veuillez insérer du papier dans l'imprimante, SVP!");
+ return;
+ }
+ case 5: {
+ MessageDialog.showError(getContext(), "Suchauffe iminante de l'imprimante, Veuillez laisser reposer!");
+ return;
+ }
+ case 6: {
+ MessageDialog.showError(getContext(), "Le capot est ouvert, veuillez fermer SVP!");
+ return;
+ }
+
+ }
+ }
+ pariViewModel.createPari(pari).observe(getViewLifecycleOwner(), new Observer>() {
@Override
public void onChanged(Result pariResult) {
- switch (pariResult.status){
+ switch (pariResult.status) {
case ERROR:
loader.dismiss();
dialog.dismiss();
@@ -594,7 +684,7 @@ public class BetValidation extends Fragment {
case SUCCESS:
try {
loader.dismiss();
- logsViewModel.insertLog(prefsHelper.get("id"), "BET", "Création du pari "+pariResult.data.getNumeroTicket()+", type de paris: "+pariResult.data.getTypesParisMises().get(0).getTypePari()+", combinaison:"+selectedHorses.getValue().stream().map(String::valueOf).collect(Collectors.joining("-")), System.currentTimeMillis());
+ logsViewModel.insertLog(prefsHelper.get("id"), "BET", "Création du pari " + pariResult.data.getNumeroTicket() + ", type de paris: " + pariResult.data.getTypesParisMises().get(0).getTypePari() + ", combinaison:" + selectedHorses.getValue().stream().map(String::valueOf).collect(Collectors.joining("-")), System.currentTimeMillis());
printPari(pariResult.data);
dialog.dismiss();
MessageDialog.showSuccess(getContext(), "Pari créé avec succès");
@@ -614,7 +704,7 @@ public class BetValidation extends Fragment {
dialog.show();
}
- void _initializeToZero(){
+ void _initializeToZero() {
selectedHorses.setValue(List.of());
binding.combination.setText("");
binding.order.setChecked(false);
@@ -625,29 +715,29 @@ public class BetValidation extends Fragment {
setupNumberGrid(binding.gridNumbers);
}
- public void calculateMise(List selectedHorses){
+ public void calculateMise(List selectedHorses) {
_notClickable(selectedHorses);
int nombreChevauxSelectionnes = selectedHorses.size();
long mise = 0;
int nonPartants = 0;
- if(shared.typeOfBet.getValue() == null || shared.selectedCourse.getValue() == null){
+ if (shared.typeOfBet.getValue() == null || shared.selectedCourse.getValue() == null) {
return;
}
- if(shared.selectedCourse.getValue().getNonPartants() != null){
+ if (shared.selectedCourse.getValue().getNonPartants() != null) {
nonPartants = shared.selectedCourse.getValue().getNonPartants().size();
}
int typeOfBetHorses = shared.typeOfBet.getValue().getNumberOfHorse();
int partants = shared.selectedCourse.getValue().getNombrePartants();
Course.TypeParis courseName = shared.typeOfBet.getValue().getName();
- if(shared.typeOfBet.getValue().getNumberOfHorse() > nombreChevauxSelectionnes){
- binding.mise.setText(mise+" CFA");
+ if (shared.typeOfBet.getValue().getNumberOfHorse() > nombreChevauxSelectionnes) {
+ binding.mise.setText(mise + " CFA");
return;
}
MiseInitiale miseModel = misesInitiales.stream()
- .filter(miseInitiale-> miseInitiale.getTypePari().equals(courseName))
+ .filter(miseInitiale -> miseInitiale.getTypePari().equals(courseName))
.findFirst()
.orElse(null);
- if(miseModel == null){
+ if (miseModel == null) {
MessageDialog.showError(getContext(), "Erreur lors de l'initialisation de la mise");
_initializeToZero();
return;
@@ -662,7 +752,7 @@ public class BetValidation extends Fragment {
// Pour COUPLE_GAGNANT ou COUPLE_PLACE: coefficient < 200
if (coeff > 200) {
// Erreur: coefficient trop élevé
- MessageDialog.showError(getContext(),"Le coefficient doit être au plus 200 pour "+typePari.toString());
+ MessageDialog.showError(getContext(), "Le coefficient doit être au plus 200 pour " + typePari.toString());
_initializeToZero();
return;
}
@@ -670,58 +760,103 @@ public class BetValidation extends Fragment {
// Pour les autres types: coefficient <= 20
if (coeff > 20) {
// Erreur: coefficient trop élevé
- MessageDialog.showError(getContext(), "Le coefficient doit être inférieur ou égal à 20 pour "+typePari.toString());
+ MessageDialog.showError(getContext(), "Le coefficient doit être inférieur ou égal à 20 pour " + typePari.toString());
_initializeToZero();
return;
}
}
mise = mise * coeff;
- if(nombreX>0){
- if(nombreChevauxSelectionnes == typeOfBetHorses){
- mise = mise * _calculateArrangement((partants - (typeOfBetHorses-nombreX) - nonPartants), nombreX);
- }else{
- if(nombreChevauxSelectionnes - typeOfBetHorses < nombreX || nombreChevauxSelectionnes - typeOfBetHorses==1){
+ if (nombreX > 0) {
+ if (nombreChevauxSelectionnes == typeOfBetHorses) {
+ mise = mise * _calculateArrangement((partants - (typeOfBetHorses - nombreX) - nonPartants), nombreX);
+ } else {
+ if (nombreChevauxSelectionnes - typeOfBetHorses < nombreX || nombreChevauxSelectionnes - typeOfBetHorses == 1) {
mise = 0;
this.mise = mise;
- binding.mise.setText(mise+" CFA");
+ binding.mise.setText(mise + " CFA");
return;
}
- mise = mise * _calculateArrangement(nombreChevauxSelectionnes - typeOfBetHorses , nombreX);
+ mise = mise * _calculateArrangement(nombreChevauxSelectionnes - typeOfBetHorses, nombreX);
}
- if(order){
- mise = mise * _calculateArrangement(typeOfBetHorses, (typeOfBetHorses-nombreX));
+ if (order) {
+ mise = mise * _calculateArrangement(typeOfBetHorses, (typeOfBetHorses - nombreX));
}
this.mise = mise;
- binding.mise.setText(mise+" CFA");
+ binding.mise.setText(mise + " CFA");
return;
}
- if(!order){
+ if (!order) {
mise = mise * _calculateCombinaison(nombreChevauxSelectionnes, typeOfBetHorses);
- }else{
+ } else {
mise = mise * _calculateArrangement(nombreChevauxSelectionnes, typeOfBetHorses);
}
this.mise = mise;
- binding.mise.setText(mise+" CFA");
+ binding.mise.setText(mise + " CFA");
}
- Long _calculateArrangement(int n, int k){
- return _calculateFactorial(n) / _calculateFactorial(n-k);
+ Long _calculateArrangement(int n, int k) {
+ return _calculateFactorial(n) / _calculateFactorial(n - k);
}
- Long _calculateCombinaison(int n, int k){
+ Long _calculateCombinaison(int n, int k) {
return _calculateFactorial(n) / (_calculateFactorial(k) * _calculateFactorial(n - k));
}
- Long _calculateFactorial(int n){
+ Long _calculateFactorial(int n) {
long f = 1;
- if(n == 0){
- return f;
+ if (n == 0) {
+ return f;
}
- for(int i = 1; i <=n; i++){
+ for (int i = 1; i <= n; i++) {
f *= i;
}
- return f;
+ return f;
+ }
+
+
+ private Bitmap resizeToPrinterWidth(Bitmap originalBitmap, int printerWidthPx) {
+ int originalWidth = originalBitmap.getWidth();
+ int originalHeight = originalBitmap.getHeight();
+ int newHeight = (originalHeight * printerWidthPx) / originalWidth;
+
+ // 1. Redimensionner sans filtre (conserve les contours nets)
+ Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap,
+ printerWidthPx,
+ newHeight,
+ false);
+
+ // 2. Créer un bitmap ARGB_8888 (meilleure qualité que RGB_565)
+ Bitmap result = Bitmap.createBitmap(printerWidthPx, newHeight, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(result);
+ canvas.drawColor(Color.WHITE);
+
+ // 3. Dessiner avec un Paint qui préserve les couleurs
+ Paint paint = new Paint();
+ paint.setAntiAlias(false); // Pas d'anti-aliasing (évite le flou)
+ canvas.drawBitmap(scaledBitmap, 0, 0, paint);
+
+ // 4. Seuillage intelligent pour garder les détails
+ for (int x = 0; x < result.getWidth(); x++) {
+ for (int y = 0; y < result.getHeight(); y++) {
+ int pixel = result.getPixel(x, y);
+ int r = Color.red(pixel);
+ int g = Color.green(pixel);
+ int b = Color.blue(pixel);
+
+ // Calculer la luminosité
+ int gray = (r + g + b) / 3;
+
+ // Seuil adaptatif : si c'est sombre, deviens noir
+ if (gray < 130) { // Seuil à 200 pour garder les gris clairs
+ result.setPixel(x, y, Color.BLACK);
+ } else {
+ result.setPixel(x, y, Color.WHITE);
+ }
+ }
+ }
+
+ return result;
}
@@ -735,6 +870,7 @@ public class BetValidation extends Fragment {
}
return bmp;
}
+
public static String generate12Digits() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 8; i++) {
diff --git a/app/src/main/java/com/example/quiz/DerniersParis.java b/app/src/main/java/com/example/quiz/DerniersParis.java
index fd283d7..38539dc 100644
--- a/app/src/main/java/com/example/quiz/DerniersParis.java
+++ b/app/src/main/java/com/example/quiz/DerniersParis.java
@@ -1,9 +1,15 @@
package com.example.quiz;
+import android.annotation.SuppressLint;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
@@ -11,15 +17,20 @@ import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.TextView;
import android.widget.Toast;
+import com.anggastudio.printama.Printama;
import com.example.quiz.data.adapter.LastBetsAdapter;
+import com.example.quiz.data.model.Course;
import com.example.quiz.data.model.Pari;
import com.example.quiz.data.model.ParisResponse;
import com.example.quiz.databinding.FragmentDerniersParisBinding;
+import com.example.quiz.utils.BluetoothUtils;
import com.example.quiz.utils.LoaderDialog;
import com.example.quiz.utils.MessageDialog;
import com.example.quiz.utils.Result;
@@ -27,8 +38,18 @@ import com.example.quiz.utils.SharedPrefsHelper;
import com.example.quiz.viewModel.LogsViewModel;
import com.example.quiz.viewModel.PariViewModel;
import com.google.android.material.appbar.MaterialToolbar;
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.WriterException;
+import com.google.zxing.common.BitMatrix;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
import dagger.hilt.android.AndroidEntryPoint;
@@ -45,13 +66,18 @@ public class DerniersParis extends Fragment {
LogsViewModel logsViewModel;
+
LoaderDialog loader;
SharedPrefsHelper prefsHelper;
PariViewModel viewModel;
+ AlertDialog dialog;
+
LastBetsAdapter adapter;
+ Map listProduits = Map.of("QUINTE", 5, "QUARTE", 4, "TIERCE", 3, "COUPLE_GAGNANT", 2, "COUPLE_PLACE", 2);
+
public DerniersParis() {
// Required empty public constructor
}
@@ -70,6 +96,7 @@ public class DerniersParis extends Fragment {
prefsHelper = SharedPrefsHelper.getInstance(getContext());
}
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -84,29 +111,203 @@ public class DerniersParis extends Fragment {
super.onViewCreated(view, savedInstanceState);
binding.lastBetsRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
viewModel = new ViewModelProvider(this).get(PariViewModel.class);
- viewModel.getDerniersParis(prefsHelper.get("id")).observe(getViewLifecycleOwner(), new Observer>>() {
+ _getLastBets();
+ }
+
+ void _getLastBets(){
+ viewModel.getDerniersParis(prefsHelper.get("id")).observe(getViewLifecycleOwner(), new Observer>>() {
+ @Override
+ public void onChanged(Result> listResult) {
+ switch (listResult.status){
+ case LOADING:
+ loader.show("Chargement des derniers paris");
+ break;
+ case ERROR:
+ loader.dismiss();
+ MessageDialog.showError(getContext(), listResult.message);
+ break;
+ case SUCCESS:
+ loader.dismiss();
+ if(adapter == null){
+ adapter = new LastBetsAdapter(listResult.data);
+ }else{
+ adapter.setData(listResult.data);
+ }
+
+ logsViewModel.insertLog(prefsHelper.get("id"), "LAST BETS", "Affichage derniers paris", System.currentTimeMillis());
+ adapter.setPariClickListener(new LastBetsAdapter.onPariClickListener() {
+ @Override
+ public void onItemClick(ParisResponse pari) {
+ if(pari.getStatutPari() != null && pari.getStatutPari() != ParisResponse.StatutPari.ENREGISTRE){
+ MessageDialog.showError(getContext(), "Ce pari ne peut pas être réimprimé!");
+ return;
+ }
+ _showPariDialog(pari);
+ }
+ @Override
+ public void onItemCancel(ParisResponse pari) {
+ if(pari.getStatutPari() != null && pari.getStatutPari() != ParisResponse.StatutPari.ENREGISTRE){
+ MessageDialog.showError(getContext(), "Ce pari ne peut pas être annulé");
+ return;
+ }
+ _cancelConfirmationDialog(pari);
+ }
+ });
+ binding.lastBetsRecyclerView.setAdapter(adapter);
+ break;
+ }
+ }
+ });
+ }
+
+ void _cancelConfirmationDialog(ParisResponse pari){
+ new AlertDialog.Builder(getContext())
+ .setTitle("Annulation du pari")
+ .setMessage("Êtes-vous sûr de vouloir annuler le pari "+pari.getNumeroTicket()+" ?")
+ .setPositiveButton("Oui", (cancelDialog, which) -> {
+ _cancelPari(pari);
+ cancelDialog.dismiss();
+ })
+ .setNegativeButton("Non", (cancelDialog, which) -> {
+ cancelDialog.dismiss();
+ }).show();
+ }
+
+ void _cancelPari(ParisResponse pari){
+ viewModel.annulerPari(pari.getNumeroTicket()).observe(getViewLifecycleOwner(), new Observer>() {
@Override
- public void onChanged(Result> listResult) {
- switch (listResult.status){
+ public void onChanged(Result result) {
+ switch (result.status){
case LOADING:
- loader.show("Chargement des derniers paris");
+ loader.show("Annulation du pari");
break;
case ERROR:
loader.dismiss();
- MessageDialog.showError(getContext(), listResult.message);
+ MessageDialog.showError(getContext(), result.message);
break;
case SUCCESS:
loader.dismiss();
- adapter = new LastBetsAdapter(listResult.data, pari -> {
- });
- logsViewModel.insertLog(prefsHelper.get("id"), "LAST BETS", "Affichage derniers paris", System.currentTimeMillis());
- binding.lastBetsRecyclerView.setAdapter(adapter);
+ MessageDialog.showSuccess(getContext(), "Pari annulé avec succès");
+ _getLastBets();
break;
}
}
});
}
+
+ @SuppressLint({"MissingInflatedId", "SetTextI18n"})
+ void _showPariDialog(ParisResponse pari){
+ LayoutInflater inflater = getLayoutInflater();
+ View view = inflater.inflate(R.layout.pari_confirmation, null);
+ TextView numero_course = (TextView) view.findViewById(R.id.alert_course_numero);
+ numero_course.setText("Numero Course: "+String.valueOf(pari.getCourseId()));
+ TextView alert_pari_type = (TextView) view.findViewById(R.id.alert_pari_type);
+ alert_pari_type.setText(String.valueOf(pari.getTypesParisMises().get(0).getTypePari()));
+ TextView is_elargie = (TextView) view.findViewById(R.id.alert_is_elargie);
+ List selectedHorses = Arrays.stream(pari.getCombinaison().split(","))
+ .map(String::trim)
+ .collect(Collectors.toList());
+ is_elargie.setText(selectedHorses.size() > listProduits.get(pari.getTypesParisMises().get(0).getTypePari())?"CE":"SI");
+ TextView alert_combinaison = (TextView) view.findViewById(R.id.alert_combinaison);
+ alert_combinaison.setText(selectedHorses.stream()
+ .map(String::valueOf)
+ .collect(Collectors.joining("-")));
+ TextView aler_coeff = (TextView) view.findViewById(R.id.alert_coeff);
+ aler_coeff.setText("Coef:"+String.valueOf(pari.getCoefficient()));
+ TextView alert_montant = (TextView) view.findViewById(R.id.alert_montant);
+ alert_montant.setText("Montant: "+String.valueOf(pari.getTypesParisMises().get(0).getMiseTotale())+" CFA");
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ builder.setView(view);
+ builder.setCancelable(false);
+ dialog = builder.create();
+ dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
+
+ view.findViewById(R.id.alert_validate).setOnClickListener(v->{
+ try {
+ _printPari(pari);
+ dialog.dismiss();
+ } catch (WriterException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ view.findViewById(R.id.alert_cancel).setOnClickListener(v -> {
+ dialog.dismiss();
+ });
+ dialog.show();
+ }
+
+
+
+ void _printPari(ParisResponse pari) throws WriterException {
+ try {
+ Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo);
+ Bitmap barcode = generateBarcodeBitmap(pari.getNumeroTicket(), 384, 100);
+ StringBuilder tspl = new StringBuilder();
+ Printama printama = Printama.with(getContext());
+ tspl.append("Bamako").append("\n");
+ tspl.append(pari.getCourseNom()).append("\n");
+ OffsetDateTime dateTime = OffsetDateTime.parse(pari.getHeureDepartPrevue() != null ? pari.getHeureDepartPrevue() : OffsetDateTime.now().toString());
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
+ String formattedDate = dateTime.format(formatter);
+ tspl.append(formattedDate).append("\n");
+ tspl.append("Course ").append(String.valueOf(pari.getCourseId())).append("\n");
+ tspl.append(printama.lineSeparator()+"\n");
+ List selectedHorses = Arrays.stream(pari.getCombinaison().split(",")).collect(Collectors.toList());
+ boolean isElargie = selectedHorses.size()> listProduits.get(pari.getTypesParisMises().get(0).getTypePari());
+ String typePari = pari.getTypesParisMises().get(0).getTypePari();
+ tspl.append(isElargie?typePari+"/Elargie":typePari).append("\n");
+ tspl.append(pari.getFormules().contains("FORMULE_COMPLETE") ?"COMBINAISON COMPLETE"+"\n":"");
+ String combinationText = selectedHorses.stream()
+ .map(String::valueOf)
+ .collect(Collectors.joining("-"));
+ tspl.append(combinationText).append("\n");
+ tspl.append("COEF: ").append(String.valueOf(pari.getCoefficient()));
+ tspl.append("\n").append(printama.lineSeparator()).append("\n");
+ tspl.append("MONTANT: ").append(pari.getMiseTotale()).append(" XOF");
+ tspl.append("\n").append(printama.lineSeparator()).append("\n");
+ tspl.append("AGENT: ").append(pari.getAgentCode()).append("\n");
+ tspl.append("DATE: ").append(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").format(OffsetDateTime.parse(pari.getDateHeurePrise()))).append("\n");
+ if (BluetoothUtils.needsBluetoothPermissions()) {
+ if (!BluetoothUtils.hasBluetoothPermission(requireContext())) {
+ // Demande la permission si non accordée
+ BluetoothUtils.requestBluetoothPermission(requireActivity());
+ return; // arrête ici, la popup va apparaître
+ }
+ }
+
+ // 2️⃣ Permission OK, on peut afficher la liste
+
+ Printama.with(getContext()).printTextBuilder(tspl, bitmap, pari.getNumeroTicket(), barcode, new Printama.PrintCallback() {
+ @Override
+ public void onResult(boolean success, String errorMessage) {
+ if(!success){
+ MessageDialog.showError(getContext(), errorMessage);
+ }else{
+ MessageDialog.showSuccess(getContext(), "Pari imprimé avec succès");
+ }
+ }
+ });
+ } catch (SecurityException e) {
+ Toast.makeText(requireContext(),
+ "Permission Bluetooth non accordée", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+
+ public Bitmap generateBarcodeBitmap(String contents, int width, int height) throws WriterException {
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.CODE_128, width, height);
+ Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ bmp.setPixel(x, y, bitMatrix.get(x, y) ? android.graphics.Color.BLACK : android.graphics.Color.WHITE);
+ }
+ }
+ return bmp;
+ }
+
+
+
@Override
public void onResume() {
super.onResume();
diff --git a/app/src/main/java/com/example/quiz/ListOFBets.java b/app/src/main/java/com/example/quiz/ListOFBets.java
index 0eca0ab..f692036 100644
--- a/app/src/main/java/com/example/quiz/ListOFBets.java
+++ b/app/src/main/java/com/example/quiz/ListOFBets.java
@@ -16,6 +16,7 @@ import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -156,6 +157,7 @@ public class ListOFBets extends Fragment {
stompManager.subscribe("courses", json->{
requireActivity().runOnUiThread(this::observe);
+ Log.d("STOMP", json);
});
MenuHost menuHost = requireActivity();
diff --git a/app/src/main/java/com/example/quiz/PageQuiz.java b/app/src/main/java/com/example/quiz/PageQuiz.java
index b8ad550..2b4fa12 100644
--- a/app/src/main/java/com/example/quiz/PageQuiz.java
+++ b/app/src/main/java/com/example/quiz/PageQuiz.java
@@ -1,5 +1,6 @@
package com.example.quiz;
import android.graphics.Color;
+import android.os.Build;
import android.os.Bundle;
import com.anggastudio.printama.Pref;
@@ -8,12 +9,18 @@ import com.example.quiz.utils.AuthNavigator;
import com.example.quiz.utils.BluetoothUtils;
import com.example.quiz.utils.MessageDialog;
import com.example.quiz.utils.SessionManager;
+import com.example.quiz.utils.SunmiPrinterManager;
import com.example.quiz.viewModel.LoginViewModel;
import com.example.quiz.viewModel.LogsViewModel;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Handler;
import android.os.Looper;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
@@ -22,6 +29,9 @@ import androidx.navigation.ui.NavigationUI;
import com.example.quiz.databinding.ActivityPageQuizBinding;
+import java.util.HashSet;
+import java.util.Set;
+
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
@@ -36,6 +46,11 @@ public class PageQuiz extends AppCompatActivity {
AuthNavigator authNavigator;
private SessionManager sessionManager;
+ String mobileName;
+
+
+ private Set> exemptedFragment = new HashSet<>();
+
private Handler handler = new Handler();
private Runnable checkRunnable;
@@ -45,7 +60,10 @@ public class PageQuiz extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ exemptedFragment.add(ServerConfig.class);
+ exemptedFragment.add(Logs.class);
sessionManager = SessionManager.newInstance(this);
+ mobileName = Build.MANUFACTURER;
binding = ActivityPageQuizBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
logsViewModel = new ViewModelProvider(this).get(LogsViewModel.class);
@@ -121,6 +139,72 @@ public class PageQuiz extends AppCompatActivity {
// }
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ View touchedView = findTouchedView(ev);
+ Fragment currentFragment = getCurrentFragment();
+ if(currentFragment != null && exemptedFragment.contains(currentFragment.getClass())){
+ return super.dispatchTouchEvent(ev);
+ }
+ if(touchedView!=null && "tag_pin_exempt".equals(touchedView.getTag())){
+ return super.dispatchTouchEvent(ev);
+ }
+ if (authNavigator.isSessionExpired()) {
+ authNavigator.showPinDialog(() -> {
+ authNavigator.updatedLastExpiredDate();
+ });
+ return false; // Consomme l'événement pour ne pas le propager
+ }
+ authNavigator.updatedLastExpiredDate();
+ return super.dispatchTouchEvent(ev);
+ }
+
+ private Fragment getCurrentFragment() {
+ FragmentManager fm = getSupportFragmentManager();
+ // Méthode 1: Par conteneur
+ Fragment fragment = fm.findFragmentById(R.id.nav_host_fragment_content_main);
+
+ // Méthode 2: Par tag si vous utilisez des tags
+ if (fragment == null) {
+ fragment = fm.findFragmentByTag("current_fragment");
+ }
+
+ return fragment;
+ }
+
+ private View findTouchedView(MotionEvent ev) {
+ float x = ev.getRawX();
+ float y = ev.getRawY();
+
+ View rootView = getWindow().getDecorView().getRootView();
+ return findViewAtPosition(rootView, (int) x, (int) y);
+ }
+
+ private View findViewAtPosition(View view, int x, int y) {
+ if (view == null) return null;
+
+ int[] location = new int[2];
+ view.getLocationOnScreen(location);
+
+ int left = location[0];
+ int top = location[1];
+ int right = left + view.getWidth();
+ int bottom = top + view.getHeight();
+
+ if (x >= left && x <= right && y >= top && y <= bottom) {
+ if (view instanceof ViewGroup) {
+ ViewGroup group = (ViewGroup) view;
+ for (int i = group.getChildCount() - 1; i >= 0; i--) {
+ View child = group.getChildAt(i);
+ View found = findViewAtPosition(child, x, y);
+ if (found != null) return found;
+ }
+ }
+ return view;
+ }
+ return null;
+ }
+
private void checkPermission(){
Pref.init(this);
if (BluetoothUtils.needsBluetoothPermissions()) {
@@ -144,7 +228,9 @@ public class PageQuiz extends AppCompatActivity {
@Override
protected void onResume() {
- checkPermission();
+ if(!mobileName.toLowerCase().contains("sunmi")){
+ checkPermission();
+ }
super.onResume();
handler = new Handler(Looper.getMainLooper());
checkRunnable = new Runnable() {
@@ -153,7 +239,7 @@ public class PageQuiz extends AppCompatActivity {
if (sessionManager.isExpired()) {
if (!authNavigator.dialogIsShowing()) {
authNavigator.showPinDialog(() -> {
- sessionManager.updateLastExpiredDate();
+ authNavigator.updatedLastExpiredDate();
handler.postDelayed(checkRunnable, 1);
});
}
diff --git a/app/src/main/java/com/example/quiz/ServerConfig.java b/app/src/main/java/com/example/quiz/ServerConfig.java
index b868498..2c400f4 100644
--- a/app/src/main/java/com/example/quiz/ServerConfig.java
+++ b/app/src/main/java/com/example/quiz/ServerConfig.java
@@ -1,7 +1,9 @@
package com.example.quiz;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
@@ -17,7 +19,9 @@ import androidx.recyclerview.widget.RecyclerView;
import android.provider.Settings;
import android.text.Editable;
import android.text.TextWatcher;
+import android.util.Log;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -41,6 +45,7 @@ import java.net.NetworkInterface;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
+import java.util.Objects;
import dagger.hilt.android.AndroidEntryPoint;
@@ -61,6 +66,8 @@ public class ServerConfig extends Fragment {
PointDeVenteAdapter pointDeVenteAdapter;
+ TpeResponse existingTpe;
+
PointDeVente pdv = null;
private PointDeVenteViewModel pointDeVenteViewModel;
@@ -100,9 +107,66 @@ public class ServerConfig extends Fragment {
toolbar.setTitle("Configuration du terminal");
toolbar.setBackgroundColor( getResources().getColor(R.color.primary_green));
}
+ if(sharedPrefsHelper.get("terminalId") != null){
+ viewModel.getTpeById(sharedPrefsHelper.get("terminalId")).observe(getViewLifecycleOwner(), new Observer>() {
+ @Override
+ public void onChanged(Result tpeResult) {
+ switch (tpeResult.status){
+ case LOADING:
+ loader.show("Chargement du TPE");
+ break;
+ case SUCCESS:
+ loader.dismiss();
+ existingTpe = tpeResult.data;
+ if( existingTpe != null && Objects.equals(sharedPrefsHelper.get("terminalId"), String.valueOf(existingTpe.getId()))){
+ _checkPdv(existingTpe);
+ return;
+ }else{
+ MessageDialog.showError(getContext(), "Ce TPE n'est pas encore configuré");
+ _startAutocomplete();
+ break;
+ }
+ case ERROR:
+ loader.dismiss();
+ MessageDialog.showError(getContext(), "Erreur lors du chargement du TPE");
+ break;
+ }
+ }
+ });
+ }
+ _startAutocomplete();
+ super.onViewCreated(view, savedInstanceState);
+ }
+
+
+ @SuppressLint("ClickableViewAccessibility")
+ void _startAutocomplete(){
pointDeVenteAdapter = new PointDeVenteAdapter();
RecyclerView recyclerView = binding.pointRecyclerView;
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+ binding.getRoot().setOnTouchListener((v, event) -> {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ // Vérifier si le clic est en dehors de l'autocomplete
+ if (binding.autocompleteContainer.getVisibility() == View.VISIBLE && !binding.pointDeVente.isEnabled()) {
+ int[] location = new int[2];
+ binding.autocompleteContainer.getLocationOnScreen(location);
+ Rect rect = new Rect(
+ location[0],
+ location[1],
+ location[0] + binding.autocompleteContainer.getWidth(),
+ location[1] + binding.autocompleteContainer.getHeight()
+ );
+
+ int x = (int) event.getRawX();
+ int y = (int) event.getRawY();
+
+ if (!rect.contains(x, y)) {
+ binding.autocompleteContainer.setVisibility(View.GONE);
+ }
+ }
+ }
+ return false;
+ });
binding.pointDeVente.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
@@ -112,7 +176,7 @@ public class ServerConfig extends Fragment {
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if(!isUserTap) return;
- if(charSequence.toString().isEmpty() || charSequence.toString().length()==0){
+ if(charSequence.toString().isEmpty() || !binding.pointDeVente.isEnabled()){
recyclerView.setVisibility(View.GONE);
binding.autocompleteContainer.setVisibility(View.GONE);
return;
@@ -157,7 +221,34 @@ public class ServerConfig extends Fragment {
}
});
- super.onViewCreated(view, savedInstanceState);
+ }
+
+ void _checkPdv(Tpe eTpe){
+ binding.numeroSerie.setText(eTpe.getNumeroSerie());
+ binding.brand.setText(eTpe.getTypeTerminal());
+ binding.model.setText(eTpe.getModeleAppareil());
+ binding.type.setText(eTpe.getTypeTerminal());
+ pointDeVenteViewModel.getPointDeVenteById(String.valueOf(eTpe.getPointDeVenteId())).observe(getViewLifecycleOwner(), new Observer>() {
+ @Override
+ public void onChanged(Result pointDeVenteResult) {
+ switch (pointDeVenteResult.status){
+ case LOADING:
+ loader.show("Chargement du point de vente");
+ break;
+ case SUCCESS:
+ loader.dismiss();
+ binding.pointDeVente.setEnabled(false);
+ binding.pointDeVente.setText(pointDeVenteResult.data.getNom());
+ binding.validate.setClickable(false);
+ MessageDialog.showSuccess(getContext(), "Ce tpe est déjà configuré");
+ break;
+ case ERROR:
+ loader.dismiss();
+ MessageDialog.showError(getContext(), "Erreur lors du chargement du point de vente");
+ break;
+ }
+ }
+ });
}
@Override
diff --git a/app/src/main/java/com/example/quiz/Settings.java b/app/src/main/java/com/example/quiz/Settings.java
index d673051..8e2bbad 100644
--- a/app/src/main/java/com/example/quiz/Settings.java
+++ b/app/src/main/java/com/example/quiz/Settings.java
@@ -134,6 +134,10 @@ public class Settings extends Fragment {
authNavigator.navigate(agentManagement);
}
});
+
+ binding.logout.setOnClickListener(v -> {
+ authNavigator.logOut();
+ });
}
diff --git a/app/src/main/java/com/example/quiz/WinTicket.java b/app/src/main/java/com/example/quiz/WinTicket.java
index 7a3aacc..aeb865c 100644
--- a/app/src/main/java/com/example/quiz/WinTicket.java
+++ b/app/src/main/java/com/example/quiz/WinTicket.java
@@ -1,26 +1,59 @@
package com.example.quiz;
+import android.annotation.SuppressLint;
+import android.graphics.Color;
import android.os.Bundle;
+import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
+import androidx.lifecycle.Observer;
+import androidx.lifecycle.ViewModelProvider;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import com.example.quiz.data.model.ParisResponse;
+import com.example.quiz.data.model.enums.PariStatut;
import com.example.quiz.databinding.FragmentWinTicketBinding;
+import com.example.quiz.utils.LoaderDialog;
+import com.example.quiz.utils.MessageDialog;
+import com.example.quiz.utils.Result;
+import com.example.quiz.utils.SharedPrefsHelper;
+import com.example.quiz.viewModel.LogsViewModel;
+import com.example.quiz.viewModel.PariViewModel;
import com.google.android.material.appbar.MaterialToolbar;
+import org.w3c.dom.Text;
+
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+
+import dagger.hilt.android.AndroidEntryPoint;
+
/**
* A simple {@link Fragment} subclass.
* Use the {@link WinTicket#newInstance} factory method to
* create an instance of this fragment.
*/
+@AndroidEntryPoint
public class WinTicket extends Fragment {
FragmentWinTicketBinding binding;
+ PariViewModel pariViewModel;
+
+ LogsViewModel logsViewModel;
+
+ SharedPrefsHelper sharedPrefsHelper;
+
+ LoaderDialog loader;
+
public WinTicket() {
// Required empty public constructor
@@ -48,6 +81,10 @@ public class WinTicket extends Fragment {
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
+ pariViewModel = new ViewModelProvider(this).get(PariViewModel.class);
+ logsViewModel = new ViewModelProvider(this).get(LogsViewModel.class);
+ sharedPrefsHelper = SharedPrefsHelper.getInstance(getContext());
+ loader = new LoaderDialog(getContext());
binding.winTicketBtnBack.setOnClickListener(v -> {
getActivity().onBackPressed();
});
@@ -58,6 +95,173 @@ public class WinTicket extends Fragment {
});
scannerDialog.show(getParentFragmentManager(), "scanner");
});
+ binding.winTicketVerificationBtn.setOnClickListener(v -> {
+ String reference = binding.referenceTicket.getText().toString();
+ if(reference.isEmpty()){
+ MessageDialog.showError(getContext(), "Veuillez donner la reference du ticket");
+ return;
+ }
+ pariViewModel.getPariByNumero(reference).observe(getViewLifecycleOwner(), new Observer>() {
+ @Override
+ public void onChanged(Result parisResponseResult) {
+ switch (parisResponseResult.status){
+ case LOADING:{
+ loader.show("Recherche du ticket");
+ break;
+ }
+ case ERROR:{
+ MessageDialog.showError(getContext(), parisResponseResult.message);
+ break;
+ }
+ case SUCCESS:{
+ if(parisResponseResult.data.getNumeroTicket().equals(reference)){
+ loader.dismiss();
+ _showDialog(parisResponseResult.data);
+ }else{
+ MessageDialog.showError(getContext(), "Le ticket n'existe pas");
+ }
+ break;
+ }
+ }
+ }
+ });
+ });
+ }
+
+ @SuppressLint("SetTextI18n")
+ void _showDialog(ParisResponse pari){
+ LayoutInflater inflater = getLayoutInflater();
+ View view = inflater.inflate(R.layout.pay_confirmation_layout, null);
+ TextView statut = (TextView) view.findViewById(R.id.tv_statut);
+ statut.setText("Statut: "+String.valueOf(pari.getStatutPari()));
+ TextView dateHeure = (TextView) view.findViewById(R.id.tv_date_heure);
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
+ dateHeure.setText(formatter.format(LocalDateTime.now()));
+ TextView numeroCourse = (TextView) view.findViewById(R.id.tv_numero_course);
+ numeroCourse.setText(String.valueOf(pari.getCourseNumero()));
+ TextView nomCourse = (TextView) view.findViewById(R.id.tv_nom_course);
+ nomCourse.setText(pari.getCourseNom());
+ TextView numeroTicket = (TextView) view.findViewById(R.id.tv_numero_ticket);
+ numeroTicket.setText(pari.getNumeroTicket());
+ TextView datePrise = (TextView) view.findViewById(R.id.tv_date_prise);
+ datePrise.setText(formatter.format(OffsetDateTime.parse(pari.getDateHeurePrise())));
+ TextView combinaison = (TextView) view.findViewById(R.id.tv_combinaison);
+ combinaison.setText(pari.getCombinaison());
+ TextView montant = (TextView) view.findViewById(R.id.tv_montant);
+ LinearLayout montantLayout = (LinearLayout) view.findViewById(R.id.tv_montant_layout);
+ Button confirmer = (Button) view.findViewById(R.id.btn_confirmer);
+ LinearLayout notesLayout = (LinearLayout) view.findViewById(R.id.notes_layout);
+ TextView notes = (TextView) view.findViewById(R.id.notes);
+
+ TextView messageStatut = (TextView) view.findViewById(R.id.tv_message_statut);
+ switch (pari.getStatutPari()){
+ case GAGNANT:{
+ messageStatut.setText("Veuillez confirmer le paiement de ce pari");
+ montant.setText(pari.getGainCalcule()+" CFA");
+ break;
+ }
+ case A_REMBOURSER:{
+ messageStatut.setText("Veuillez confirmer le remboursement de ce pari");
+ montant.setText(pari.getMiseTotale()+" CFA");
+ break;
+ }
+ case PAYE:{
+ messageStatut.setText("Ce pari a déjà été payé");
+ montant.setText(pari.getGainCalcule()+" CFA");
+ notesLayout.setVisibility(View.VISIBLE);
+ notes.setText(pari.getNotes());
+ confirmer.setVisibility(View.GONE);
+ break;
+ }
+ default:{
+ montantLayout.setVisibility(View.GONE);
+ statut.setTextColor(Color.parseColor("#cf1c08"));
+ messageStatut.setVisibility(View.GONE);
+ confirmer.setVisibility(View.GONE);
+ break;
+ }
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ builder.setView(view);
+ AlertDialog dialog = builder.create();
+ Button annuler = (Button) view.findViewById(R.id.btn_annuler);
+ annuler.setOnClickListener(v -> {
+ dialog.dismiss();
+ });
+ confirmer.setOnClickListener(v -> {
+ switch (pari.getStatutPari()){
+ case A_REMBOURSER:{
+ pariViewModel.rembourserPari(pari.getNumeroTicket()).observe(getViewLifecycleOwner(), new Observer>() {
+ @Override
+ public void onChanged(Result pariResponseResult) {
+ switch (pariResponseResult.status){
+ case LOADING: {
+ loader.show("Remboursement en cours");
+ break;
+ }
+ case ERROR: {
+ loader.dismiss();
+ MessageDialog.showError(getContext(), pariResponseResult.message);
+ break;
+ }
+ case SUCCESS: {
+ loader.dismiss();
+ if(sharedPrefsHelper.get("id") == null){
+ MessageDialog.showError(getContext(), "Erreur de connexion");
+ return;
+ }
+ logsViewModel.insertLog(sharedPrefsHelper.get("id"), "REMBOURSEMENT TICKET", "Remboursement du ticket numéro "+ pari.getNumeroTicket()+" montant "+pari.getMiseTotale(), System.currentTimeMillis());
+ MessageDialog.showSuccess(getContext(), "Remboursement effectué avec succès");
+ binding.referenceTicket.setText("");
+ dialog.dismiss();
+ break;
+ }
+ }
+ }
+ });
+ break;
+ }
+ case GAGNANT:{
+ pariViewModel.payerPari(pari.getNumeroTicket()).observe(getViewLifecycleOwner(), new Observer>() {
+ @Override
+ public void onChanged(Result pariResponseResult) {
+ switch (pariResponseResult.status){
+ case LOADING: {
+ loader.show("Paiement en cours");
+ break;
+ }
+ case ERROR: {
+ loader.dismiss();
+ MessageDialog.showError(getContext(), pariResponseResult.message);
+ break;
+ }
+ case SUCCESS: {
+ loader.dismiss();
+ if(sharedPrefsHelper.get("id") == null){
+ MessageDialog.showError(getContext(), "Erreur de connexion");
+ return;
+ }
+ logsViewModel.insertLog(sharedPrefsHelper.get("id"), "PAIEMENT TICKET", "Paiement du ticket numéro "+ pari.getNumeroTicket()+" montant "+pari.getGainCalcule(), System.currentTimeMillis());
+ binding.referenceTicket.setText("");
+ MessageDialog.showSuccess(getContext(), "Paiement effectué avec succès");
+ dialog.dismiss();
+ break;
+ }
+ }
+ }
+ });
+ break;
+ }
+ default:{
+ dialog.dismiss();
+ MessageDialog.showError(getContext(), "Action non comprise pour ce ticket");
+ binding.referenceTicket.setText("");
+ break;
+ }
+ }
+ });
+ dialog.show();
}
@Override
diff --git a/app/src/main/java/com/example/quiz/data/adapter/LastBetsAdapter.java b/app/src/main/java/com/example/quiz/data/adapter/LastBetsAdapter.java
index ff78ef5..1590207 100644
--- a/app/src/main/java/com/example/quiz/data/adapter/LastBetsAdapter.java
+++ b/app/src/main/java/com/example/quiz/data/adapter/LastBetsAdapter.java
@@ -1,9 +1,16 @@
package com.example.quiz.data.adapter;
+import static java.security.AccessController.getContext;
+
+import android.graphics.Color;
import android.text.TextUtils;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
@@ -17,21 +24,23 @@ import java.util.List;
public class LastBetsAdapter extends RecyclerView.Adapter {
private List listeParis = new ArrayList<>(); // évite les NPE
- private OnBetClick onBetClick; // peut être null si tu veux
- public interface OnBetClick {
+ private onPariClickListener listener;
+
+ public interface onPariClickListener {
void onItemClick(ParisResponse pari);
+
+ void onItemCancel(ParisResponse pari);
}
- public LastBetsAdapter(List listeParis, OnBetClick onBetClick) {
+ public void setPariClickListener(onPariClickListener listener) {
+ this.listener = listener;
+ }
+
+ public LastBetsAdapter(List listeParis) {
if (listeParis != null) this.listeParis = listeParis;
- this.onBetClick = onBetClick;
}
- // Constructeur vide utile si tu veux créer puis setData ensuite
- public LastBetsAdapter(OnBetClick onBetClick) {
- this.onBetClick = onBetClick;
- }
public void setData(List newList) {
if (newList == null) {
@@ -77,10 +86,44 @@ public class LastBetsAdapter extends RecyclerView.Adapter {
- if (onBetClick != null) onBetClick.onItemClick(pari);
+ holder.btnAnnuler.setOnClickListener(v -> {
+ if (listener != null) {
+ listener.onItemCancel(pari);
+ }
+ });
+
+ holder.btnImprimer.setOnClickListener(v -> {
+ if (listener != null) {
+ listener.onItemClick(pari);
+ }
});
}
@@ -90,7 +133,8 @@ public class LastBetsAdapter extends RecyclerView.Adapter> derniersParis(@Path("agentId") String agentId);
- @PATCH("paris/numero/{numeroTicket}/statut")
- Call annulerPari(@Path("numeroTicket") String numeroTicket,
- @Body() CancelParisPaylaod cancelParisPaylaod);
+ @PATCH("paris/numero/{numeroTicket}/cancel")
+ Call annulerPari(@Path("numeroTicket") String numeroTicket);
+ @PATCH("paris/numero/{numeroTicket}/rembourser")
+ Call rembourserPari(@Path("numeroTicket") String numeroTicket);
+
+ @PATCH("paris/numero/{numeroTicket}/pay")
+ Call payerPari(@Path("numeroTicket") String numeroTicket);
+
+
+ @GET("paris/numero/{numeroTicket}")
+ Call getPariByNumero(@Path("numeroTicket") String numeroTicket);
@GET("paris/agent/{agentId}/solde/course/{courseId}")
Call getSoldeByCourse(@Path("agentId") String createdBy, @Path("courseId") String courseId);
@@ -58,9 +66,15 @@ public interface ApiService {
@POST("terminaux")
Call createTpe(@Body Tpe tpe);
+ @GET("terminaux/{id}")
+ Call getTpeById(@Path("id") String id);
+
@GET("points-de-vente")
Call> getPointsDeVente(@Query("nom") String nom);
+ @GET("points-de-vente/{id}")
+ Call getPointDeVenteById(@Path("id") String id);
+
@PATCH("agents/me/pin")
Call changePin(@Body ChangePin pin);
diff --git a/app/src/main/java/com/example/quiz/data/remote/StompManager.java b/app/src/main/java/com/example/quiz/data/remote/StompManager.java
index 7238498..e60095b 100644
--- a/app/src/main/java/com/example/quiz/data/remote/StompManager.java
+++ b/app/src/main/java/com/example/quiz/data/remote/StompManager.java
@@ -61,7 +61,7 @@ public class StompManager {
}
// URL de connexion WebSocket
- String url = "wss://boxer-adapting-bluegill.ngrok-free.app/ws";
+ String url = "wss://alr.pmu.ml/ws";
try {
// Créer le client STOMP
diff --git a/app/src/main/java/com/example/quiz/data/repository/AgentRepository.java b/app/src/main/java/com/example/quiz/data/repository/AgentRepository.java
index f8126e6..aa32e60 100644
--- a/app/src/main/java/com/example/quiz/data/repository/AgentRepository.java
+++ b/app/src/main/java/com/example/quiz/data/repository/AgentRepository.java
@@ -5,11 +5,14 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.example.quiz.data.model.Course;
+import com.example.quiz.data.model.ResponseError;
import com.example.quiz.data.model.Restriction;
import com.example.quiz.data.model.dtos.auth.User;
import com.example.quiz.data.remote.ApiService;
import com.example.quiz.utils.Result;
+import com.google.gson.Gson;
+import java.io.IOException;
import java.util.List;
import javax.inject.Inject;
@@ -34,7 +37,14 @@ public class AgentRepository {
if (response.isSuccessful()) {
liveAgents.postValue(Result.success(response.body()));
} else {
- liveAgents.postValue(Result.error(response.message()));
+ try {
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ liveAgents.postValue(Result.error(errorResponse.getMessage()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
}
@Override
@@ -54,7 +64,14 @@ public class AgentRepository {
if (response.isSuccessful()) {
liveAgent.postValue(Result.success(response.body()));
} else {
- liveAgent.postValue(Result.error(response.message()));
+ try {
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ liveAgent.postValue(Result.error(errorResponse.getMessage()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
}
@Override
@@ -74,7 +91,14 @@ public class AgentRepository {
if (response.isSuccessful()) {
liveAvailableBets.postValue(Result.success(response.body()));
} else {
- liveAvailableBets.postValue(Result.error(response.message()));
+ try{
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ liveAvailableBets.postValue(Result.error(errorResponse.getMessage()));
+ }catch (Exception e){
+ liveAvailableBets.postValue(Result.error(e.getMessage()));
+ }
}
}
@Override
@@ -94,7 +118,14 @@ public class AgentRepository {
if (response.isSuccessful()) {
liveSetAccess.postValue(Result.success(null));
} else {
- liveSetAccess.postValue(Result.error(response.message()));
+ try {
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ liveSetAccess.postValue(Result.error(errorResponse.getMessage()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
}
@Override
@@ -114,7 +145,14 @@ public class AgentRepository {
if (response.isSuccessful()) {
liveSetRestrictions.postValue(Result.success(null));
} else {
- liveSetRestrictions.postValue(Result.error(response.message()));
+ try {
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ liveSetRestrictions.postValue(Result.error(errorResponse.getMessage()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
}
@Override
diff --git a/app/src/main/java/com/example/quiz/data/repository/CourseRepository.java b/app/src/main/java/com/example/quiz/data/repository/CourseRepository.java
index 33ec1c2..e61b997 100644
--- a/app/src/main/java/com/example/quiz/data/repository/CourseRepository.java
+++ b/app/src/main/java/com/example/quiz/data/repository/CourseRepository.java
@@ -7,8 +7,10 @@ import androidx.lifecycle.MutableLiveData;
import com.example.quiz.data.model.Course;
import com.example.quiz.data.model.PagedModel;
+import com.example.quiz.data.model.ResponseError;
import com.example.quiz.data.remote.ApiService;
import com.example.quiz.utils.Result;
+import com.google.gson.Gson;
import javax.inject.Inject;
@@ -33,22 +35,15 @@ public class CourseRepository {
public void onResponse(Call> call, Response> response) {
if(response.isSuccessful()){
liveCourses.postValue(Result.success(response.body()));
-// PagedModel openedPagesCourses = new PagedModel<>();
-// List listOfCourses = new ArrayList<>();
-// for(Course course: response.body().getContent()){
-// if(course.getStatut().equals(OPENED_STATUT)){
-// listOfCourses.add(course);
-// }
-// }
-//// openedPagesCourses.setTotalPages(response.body().getTotalPages());
-//// openedPagesCourses.setTotalElements(response.body().getTotalElements());
-//// openedPagesCourses.setPageable(response.body().getPageable());
-//// openedPagesCourses.setNumberOfElements(response.body().getNumberOfElements());
-//// openedPagesCourses.setSize(response.body().getSize());
-//// openedPagesCourses.setContent(listOfCourses);
-// liveCourses.postValue(Result.success(response.body()));
}else{
- liveCourses.postValue(Result.error(response.message()));
+ try{
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ liveCourses.postValue(Result.error(errorResponse.getMessage()));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
}
diff --git a/app/src/main/java/com/example/quiz/data/repository/LoginRepository.java b/app/src/main/java/com/example/quiz/data/repository/LoginRepository.java
index 93331bc..2750031 100644
--- a/app/src/main/java/com/example/quiz/data/repository/LoginRepository.java
+++ b/app/src/main/java/com/example/quiz/data/repository/LoginRepository.java
@@ -5,6 +5,7 @@ import android.util.Log;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
+import com.example.quiz.data.model.ResponseError;
import com.example.quiz.data.model.dtos.auth.ChangePin;
import com.example.quiz.data.model.dtos.auth.LoginPayload;
import com.example.quiz.data.model.dtos.auth.LoginResponse;
@@ -12,6 +13,9 @@ import com.example.quiz.data.model.dtos.auth.User;
import com.example.quiz.data.remote.ApiService;
import com.example.quiz.data.remote.TokenManager;
import com.example.quiz.utils.Result;
+import com.google.gson.Gson;
+
+import java.io.IOException;
import javax.inject.Inject;
@@ -37,10 +41,16 @@ public class LoginRepository {
public void onResponse(Call call, Response response) {
if(response.isSuccessful()){
liveLogin.postValue(Result.success(response.body()));
- Log.d("TOKEN", response.body().getToken());
tokenManager.saveToken(response.body().getToken());
}else{
- liveLogin.postValue(Result.error(response.toString()));
+ try {
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ liveLogin.postValue(Result.error(errorResponse.getMessage()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
}
@@ -64,7 +74,14 @@ public class LoginRepository {
if(response.isSuccessful()) {
liveUser.postValue(Result.success(response.body()));
}else {
- liveUser.postValue(Result.error(response.message()));
+ try {
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ liveUser.postValue(Result.error(errorResponse.getMessage()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
}
@Override
diff --git a/app/src/main/java/com/example/quiz/data/repository/PariMiseRepository.java b/app/src/main/java/com/example/quiz/data/repository/PariMiseRepository.java
index c7506b8..6d17815 100644
--- a/app/src/main/java/com/example/quiz/data/repository/PariMiseRepository.java
+++ b/app/src/main/java/com/example/quiz/data/repository/PariMiseRepository.java
@@ -1,13 +1,17 @@
package com.example.quiz.data.repository;
+import android.util.Log;
+
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.example.quiz.data.model.MiseInitiale;
import com.example.quiz.data.model.PariMise;
+import com.example.quiz.data.model.ResponseError;
import com.example.quiz.data.remote.ApiService;
import com.example.quiz.data.remote.TokenManager;
import com.example.quiz.utils.Result;
+import com.google.gson.Gson;
import java.util.List;
@@ -34,7 +38,14 @@ public class PariMiseRepository {
if (response.isSuccessful()) {
livePariMise.postValue(Result.success(response.body()));
}else{
- livePariMise.postValue(Result.error(response.message()));
+ try{
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ livePariMise.postValue(Result.error(errorResponse.getMessage()));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
}
@Override
diff --git a/app/src/main/java/com/example/quiz/data/repository/PariRepository.java b/app/src/main/java/com/example/quiz/data/repository/PariRepository.java
index 047ac96..ddc31cf 100644
--- a/app/src/main/java/com/example/quiz/data/repository/PariRepository.java
+++ b/app/src/main/java/com/example/quiz/data/repository/PariRepository.java
@@ -8,10 +8,12 @@ import androidx.lifecycle.MutableLiveData;
import com.example.quiz.data.model.Pari;
import com.example.quiz.data.model.ParisResponse;
+import com.example.quiz.data.model.ResponseError;
import com.example.quiz.data.model.dtos.paris.CancelParisPaylaod;
import com.example.quiz.data.model.dtos.paris.SoldeResponse;
import com.example.quiz.data.remote.ApiService;
import com.example.quiz.utils.Result;
+import com.google.gson.Gson;
import java.util.Collections;
import java.util.List;
@@ -44,13 +46,10 @@ public class PariRepository {
} else {
// On récupère l'erreur exacte envoyée par le backend
try {
- Map errorBody = Collections.emptyMap();
- if(response.errorBody() != null){
- errorBody = (Map) response.errorBody();
- }
- Log.d("PariRepository", response.errorBody().toString());
- pariResponse.postValue(Result.error(errorBody.get("message")));
-
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ pariResponse.postValue(Result.error(errorResponse.getMessage()));
} catch (Exception e) {
pariResponse.postValue(Result.error("Erreur serveur"));
}
@@ -76,10 +75,10 @@ public class PariRepository {
derniersParis.postValue(Result.success(response.body()));
}else{
try{
- String errorBody = response.errorBody() != null ?
- response.errorBody().string() : "Erreur inconnue";
-
- derniersParis.postValue(Result.error(errorBody));
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ derniersParis.postValue(Result.error(errorResponse.getMessage()));
}catch (Exception e){
derniersParis.postValue(Result.error(e.getMessage()));
}
@@ -95,21 +94,74 @@ public class PariRepository {
return derniersParis;
}
- public LiveData> annulerPari(String numeroTicket){
+ public LiveData> payTicket(String numeroTicket){
MutableLiveData> pariResponse = new MutableLiveData<>();
pariResponse.setValue(Result.loading());
- CancelParisPaylaod cancelParisPaylaod = new CancelParisPaylaod("ANNULE");
- apiService.annulerPari(numeroTicket, cancelParisPaylaod).enqueue(new Callback(){
+ apiService.payerPari(numeroTicket).enqueue(new Callback(){
@Override
public void onResponse(Call call, Response response) {
if(response.isSuccessful()){
pariResponse.postValue(Result.success(response.body()));
}else{
try{
- String errorBody = response.errorBody() != null ?
- response.errorBody().string() : "Erreur inconnue";
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ pariResponse.postValue(Result.error(errorResponse.getMessage()));
+ }catch (Exception e){
+ pariResponse.postValue(Result.error(e.getMessage()));
+ }
+ }
+ };
+ @Override
+ public void onFailure(Call call, Throwable throwable) {
+ pariResponse.postValue(Result.error(throwable.getMessage()));
+ }
+ });
+ return pariResponse;
+ }
- pariResponse.postValue(Result.error(errorBody));
+ public LiveData> rembourserTicket(String numeroTicket){
+ MutableLiveData> pariResponse = new MutableLiveData<>();
+ pariResponse.setValue(Result.loading());
+ apiService.rembourserPari(numeroTicket).enqueue(new Callback(){
+ @Override
+ public void onResponse(Call call, Response response) {
+ if(response.isSuccessful()){
+ pariResponse.postValue(Result.success(response.body()));
+ }else{
+ try{
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ pariResponse.postValue(Result.error(errorResponse.getMessage()));
+ }catch (Exception e){
+ pariResponse.postValue(Result.error(e.getMessage()));
+ }
+ }
+ }
+ @Override
+ public void onFailure(Call call, Throwable throwable) {
+ pariResponse.postValue(Result.error(throwable.getMessage()));
+ }
+ });
+ return pariResponse;
+ }
+
+ public LiveData> annulerPari(String numeroTicket){
+ MutableLiveData> pariResponse = new MutableLiveData<>();
+ pariResponse.setValue(Result.loading());
+ apiService.annulerPari(numeroTicket).enqueue(new Callback(){
+ @Override
+ public void onResponse(Call call, Response response) {
+ if(response.isSuccessful()){
+ pariResponse.postValue(Result.success(response.body()));
+ }else{
+ try{
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ pariResponse.postValue(Result.error(errorResponse.getMessage()));
}catch (Exception e){
pariResponse.postValue(Result.error(e.getMessage()));
}
@@ -134,7 +186,10 @@ public class PariRepository {
solde.postValue(Result.success(response.body()));
}else{
try{
- solde.postValue(Result.error(response.errorBody().string()));
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ solde.postValue(Result.error(errorResponse.getMessage()));
}catch (Exception e){
solde.postValue(Result.error(e.getMessage()));
}
@@ -159,7 +214,10 @@ public class PariRepository {
solde.postValue(Result.success(response.body()));
}else{
try {
- solde.postValue(Result.error(response.errorBody().string()));
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ solde.postValue(Result.error(errorResponse.getMessage()));
}catch (Exception e){
solde.postValue(Result.error(e.getMessage()));
}
@@ -174,4 +232,32 @@ public class PariRepository {
return solde;
}
+ public LiveData> getPariByNumero(String numeroTicket) {
+ MutableLiveData> pari = new MutableLiveData<>();
+ pari.setValue(Result.loading());
+ apiService.getPariByNumero(numeroTicket).enqueue(new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ if (response.isSuccessful()) {
+ pari.postValue(Result.success(response.body()));
+ }else{
+ try {
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ pari.postValue(Result.error(errorResponse.getMessage()));
+ }catch (Exception e){
+ pari.postValue(Result.error(e.getMessage()));
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable throwable) {
+ pari.postValue(Result.error(throwable.getMessage()));
+ }
+ });
+ return pari;
+ }
+
}
diff --git a/app/src/main/java/com/example/quiz/data/repository/PointDeVenteRepository.java b/app/src/main/java/com/example/quiz/data/repository/PointDeVenteRepository.java
index 28d250c..039163b 100644
--- a/app/src/main/java/com/example/quiz/data/repository/PointDeVenteRepository.java
+++ b/app/src/main/java/com/example/quiz/data/repository/PointDeVenteRepository.java
@@ -5,10 +5,14 @@ import androidx.lifecycle.MutableLiveData;
import com.example.quiz.data.model.PagedModel;
import com.example.quiz.data.model.PointDeVente;
+import com.example.quiz.data.model.ResponseError;
import com.example.quiz.data.remote.ApiService;
import com.example.quiz.utils.Result;
+import com.google.gson.Gson;
+import java.io.IOException;
+
import javax.inject.Inject;
import retrofit2.*;
@@ -36,18 +40,14 @@ public class PointDeVenteRepository {
if (response.isSuccessful() && response.body() != null) {
result.postValue(Result.success(response.body()));
} else {
-
- String errorMessage = "Erreur inconnue";
-
try {
- if (response.errorBody() != null) {
- errorMessage = response.errorBody().string();
- }
- } catch (Exception e) {
- errorMessage = e.getMessage();
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ result.postValue(Result.error(errorResponse.getMessage()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
}
-
- result.postValue(Result.error(errorMessage));
}
}
@@ -62,4 +62,33 @@ public class PointDeVenteRepository {
return result;
}
+
+ public LiveData> getPointDeVenteById(String id) {
+ MutableLiveData> result = new MutableLiveData<>();
+ result.setValue(Result.loading());
+ apiService.getPointDeVenteById(id).enqueue(new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ if(response.isSuccessful()){
+ result.postValue(Result.success(response.body()));
+ }else{
+ try {
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ result.postValue(Result.error(errorResponse.getMessage()));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable throwable) {
+ result.postValue(Result.error(throwable.getMessage()));
+ }
+ });
+ return result;
+ }
+
}
diff --git a/app/src/main/java/com/example/quiz/data/repository/TpeRepository.java b/app/src/main/java/com/example/quiz/data/repository/TpeRepository.java
index 6d134b4..6d57c87 100644
--- a/app/src/main/java/com/example/quiz/data/repository/TpeRepository.java
+++ b/app/src/main/java/com/example/quiz/data/repository/TpeRepository.java
@@ -3,10 +3,12 @@ package com.example.quiz.data.repository;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
+import com.example.quiz.data.model.ResponseError;
import com.example.quiz.data.model.Tpe;
import com.example.quiz.data.model.TpeResponse;
import com.example.quiz.data.remote.ApiService;
import com.example.quiz.utils.Result;
+import com.google.gson.Gson;
import javax.inject.Inject;
@@ -33,7 +35,43 @@ public class TpeRepository {
if (response.isSuccessful()) {
tpeLiveData.postValue(Result.success(response.body()));
} else {
- tpeLiveData.postValue(Result.error(response.message()));
+ try{
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ tpeLiveData.postValue(Result.error(errorResponse.getMessage()));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable throwable) {
+ tpeLiveData.postValue(Result.error(throwable.getMessage()));
+ }
+ });
+ return tpeLiveData;
+ }
+
+
+ public LiveData> getTpeById(String id) {
+ MutableLiveData> tpeLiveData = new MutableLiveData<>();
+ tpeLiveData.setValue(Result.loading());
+ apiService.getTpeById(id).enqueue(new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ if (response.isSuccessful()) {
+ tpeLiveData.postValue(Result.success(response.body()));
+ } else {
+ try{
+ String error = response.errorBody().string();
+ Gson gson = new Gson();
+ ResponseError errorResponse = gson.fromJson(error, ResponseError.class);
+ tpeLiveData.postValue(Result.error(errorResponse.getMessage()));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
}
diff --git a/app/src/main/java/com/example/quiz/utils/AuthNavigator.java b/app/src/main/java/com/example/quiz/utils/AuthNavigator.java
index f77aac9..3a984b2 100644
--- a/app/src/main/java/com/example/quiz/utils/AuthNavigator.java
+++ b/app/src/main/java/com/example/quiz/utils/AuthNavigator.java
@@ -61,14 +61,15 @@ public class AuthNavigator {
return;
}
if (sessionManager.isExpired()) {
- showPinDialog(() -> {
- sessionManager.updateLastExpiredDate();
- fragmentManager.beginTransaction()
- .replace(R.id.nav_host_fragment_content_main, destinationFragment)
- .addToBackStack(null)
- .commit();
- });
-
+ if(!dialogIsShowing()){
+ showPinDialog(() -> {
+ sessionManager.updateLastExpiredDate();
+ fragmentManager.beginTransaction()
+ .replace(R.id.nav_host_fragment_content_main, destinationFragment)
+ .addToBackStack(null)
+ .commit();
+ });
+ }
} else {
fragmentManager.beginTransaction()
.replace(R.id.nav_host_fragment_content_main, destinationFragment)
@@ -143,6 +144,15 @@ public class AuthNavigator {
return dialog.isShowing();
}
+ public boolean isSessionExpired(){
+ return sessionManager.isExpired();
+ }
+
+
+ public void updatedLastExpiredDate(){
+ sessionManager.updateLastExpiredDate();
+ }
+
private void loginSuccess(LoginResponse loginResponse){
String terminalId = prefsHelper.get("terminalId");
if(terminalId == null){
@@ -158,4 +168,14 @@ public class AuthNavigator {
prefsHelper.save("isSupAgent", isSupAgent);
}
+ public void logOut (){
+ prefsHelper.save("id", null);
+ prefsHelper.save("firstName", null);
+ prefsHelper.save("lastName", null);
+ prefsHelper.save("profile", null);
+ prefsHelper.save("code", null);
+ prefsHelper.save("isSupAgent", null);
+ sessionManager.setToExpire();
+ }
+
}
diff --git a/app/src/main/java/com/example/quiz/utils/SessionManager.java b/app/src/main/java/com/example/quiz/utils/SessionManager.java
index b0104b0..c8724ab 100644
--- a/app/src/main/java/com/example/quiz/utils/SessionManager.java
+++ b/app/src/main/java/com/example/quiz/utils/SessionManager.java
@@ -31,6 +31,10 @@ public class SessionManager {
lastExpiredDate = LocalDateTime.now();
}
+ public void setToExpire(){
+ lastExpiredDate = null;
+ }
+
public boolean isExpired() {
if (lastExpiredDate == null) {
return true;
diff --git a/app/src/main/java/com/example/quiz/utils/SunmiPrinterManager.java b/app/src/main/java/com/example/quiz/utils/SunmiPrinterManager.java
new file mode 100644
index 0000000..34436ee
--- /dev/null
+++ b/app/src/main/java/com/example/quiz/utils/SunmiPrinterManager.java
@@ -0,0 +1,275 @@
+package com.example.quiz.utils;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.sunmi.peripheral.printer.InnerPrinterCallback;
+import com.sunmi.peripheral.printer.InnerPrinterManager;
+import com.sunmi.peripheral.printer.InnerResultCallback;
+import com.sunmi.peripheral.printer.SunmiPrinterService;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+public class SunmiPrinterManager {
+
+ private static final String TAG = "SunmiPrinterManager";
+ private static SunmiPrinterManager instance;
+
+ private static final int MAX_CHAR_2_INCH = 32;
+ private static Context context;
+
+ private SunmiPrinterService sunmiPrinter;
+
+ private SunmiPrinterManager() {}
+
+ public static SunmiPrinterManager getInstance(Context ctx) {
+ if (instance == null) {
+ instance = new SunmiPrinterManager();
+ context = ctx.getApplicationContext();
+ }
+ return instance;
+ }
+
+ // 🔌 Bind UNE SEULE FOIS
+ public void connectPrinter(Consumer status) {
+ Log.d("######", "Point d'entrée printer");
+ try {
+ InnerPrinterManager.getInstance().bindService(context, new InnerPrinterCallback() {
+ @Override
+ protected void onConnected(SunmiPrinterService service) {
+ Log.d("######", "Connecté printer");
+ sunmiPrinter = service;
+ status.accept(true);
+ }
+
+ @Override
+ protected void onDisconnected() {
+ Log.d("######", "Déconnecté printer");
+ sunmiPrinter = null;
+ status.accept(false);
+ }
+ });
+ } catch (Exception e) {
+ Log.e(TAG, "#################Erreur bindService"+String.valueOf(e));
+ }
+ }
+
+ // ✅ simple check
+
+ // 🖨️ Impression robuste
+ public void printText(String text, PrinterListener listener) {
+ try {
+ sunmiPrinter.printText(text + "\n", new InnerResultCallback() {
+
+ @Override
+ public void onRunResult(boolean isSuccess) {
+ if(!isSuccess){
+ try {
+ throw new Exception("Impression", new Throwable("Erreur lors d'impression!"));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Override
+ public void onReturnString(String result) {
+ // rarement utile
+ }
+
+ @Override
+ public void onRaiseException(int code, String msg) {
+ listener.onError(msg);
+ listener.onResult(code);
+ }
+
+
+ @Override
+ public void onPrintResult(int code, String msg) {
+ listener.onResult(code);
+ listener.onError(msg);
+ }
+ });
+
+ } catch (Exception e) {
+ if (listener != null) {
+ listener.onError(e.getMessage());
+ }
+ }
+ }
+
+ public int getMaxChar(){
+ return MAX_CHAR_2_INCH;
+ }
+
+ public boolean printPari(Bitmap logo, Bitmap barcode, String numeroTicket, String text){
+ try{
+ printSimpleImage(logo);
+ printTextSimple("\n"+separationText()+"\n");
+ printSimpleImage(barcode);
+ setAlignment(1, new PrinterListener() {
+ @Override
+ public void onResult(int code) {
+
+ }
+ @Override
+ public void onError(String errorMessage) {
+
+ }
+ });
+ printTextSimple(numeroTicket);
+ printTextSimple("\n"+separationText()+"\n");
+ setAlignment(0, new PrinterListener() {
+ @Override
+ public void onResult(int code) {}
+ @Override
+ public void onError(String errorMessage) {}
+ });
+ printTextSimple(text);
+ printTextSimple("\n"+separationText()+"\n");
+ setAlignment(1, new PrinterListener() {
+ @Override
+ public void onResult(int code) {}
+ @Override
+ public void onError(String errorMessage) {}
+ });
+ printTextSimple("Powered by PMU-MALI");
+ printTextSimple("\n"+separationText()+"\n");
+ printTextSimple(" ");
+ printTextSimple(" ");
+ return true;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String separationText(){
+ return "-".repeat(MAX_CHAR_2_INCH);
+ }
+
+
+ public void printSimpleImage(Bitmap bitmap){
+ printImage(bitmap, new PrinterListener() {
+ @Override
+ public void onResult(int code) {
+ Log.d(TAG, "Print OK");
+ }
+ @Override
+ public void onError(String errorMessage) {
+ Log.e(TAG, errorMessage);
+ }
+ });
+ }
+
+ // version simple
+ public void printTextSimple(String text) {
+ printText(text, new PrinterListener() {
+ @Override
+ public void onResult(int code) {
+ Log.d(TAG, "Print OK");
+ }
+
+ @Override
+ public void onError(String errorMessage) {
+ Log.e(TAG, errorMessage);
+ }
+ });
+ }
+
+ // Dans SunmiPrinterManager.java
+
+ public void setAlignment(int alignment, PrinterListener listener) {
+ try {
+ // Appel au SDK Sunmi : 0=gauche, 1=centre, 2=droite
+ sunmiPrinter.setAlignment(alignment, new InnerResultCallback() {
+ @Override
+ public void onRunResult(boolean isSuccess) throws RemoteException {
+ if(!isSuccess){
+ try {
+ throw new Exception("Alignement", new Throwable("L'alignement n'a pas pu être défini"));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Override
+ public void onReturnString(String result) throws RemoteException {
+
+ }
+
+ @Override
+ public void onRaiseException(int code, String msg) throws RemoteException {
+ listener.onError(msg);
+ listener.onResult(code);
+ }
+
+ @Override
+ public void onPrintResult(int code, String msg) throws RemoteException {
+
+ }
+ });
+ } catch (Exception e) {
+ if (listener != null) listener.onError(e.getMessage());
+ }
+ }
+
+ public void printImage(Bitmap bitmap, PrinterListener listener){
+ try {
+ // La plupart des imprimantes Sunmi utilisent cette méthode
+ // Le paramètre '0' correspond généralement à l'alignement (0 = gauche)
+ sunmiPrinter.printBitmap(bitmap, new InnerResultCallback() {
+ @Override
+ public void onRunResult(boolean isSuccess) {
+ if(!isSuccess){
+ try {
+ throw new Exception("Impression", new Throwable("Erreur lors d'impression d'une image!"));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Override
+ public void onReturnString(String result) {
+ // Pas utile
+ }
+
+ @Override
+ public void onRaiseException(int code, String msg) {
+ Log.e(TAG, "onRaiseException: "+String.valueOf(code));
+ listener.onResult(code);
+ listener.onError(msg);
+ }
+
+ @Override
+ public void onPrintResult(int code, String msg) {
+ Log.e(TAG, "onPrintResult: "+String.valueOf(code));
+ listener.onResult(code);
+ listener.onError(msg);
+ }
+ // N'oublie pas les autres callbacks vides (onRunResult, etc.)
+ });
+ } catch (Exception e) {
+ listener.onError(e.getMessage());
+ }
+ }
+
+
+
+ public int printerStatus(){
+ try {
+ return sunmiPrinter.updatePrinterState();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public interface PrinterListener {
+ void onResult(int code);
+ void onError(String errorMessage);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/quiz/viewModel/PariViewModel.java b/app/src/main/java/com/example/quiz/viewModel/PariViewModel.java
index 8ec6a59..9eb81ac 100644
--- a/app/src/main/java/com/example/quiz/viewModel/PariViewModel.java
+++ b/app/src/main/java/com/example/quiz/viewModel/PariViewModel.java
@@ -24,10 +24,17 @@ public class PariViewModel extends ViewModel {
private LiveData> pariAnnule;
+ private LiveData> pariPaye;
+
+
+ private LiveData> pariByNumero;
+
private LiveData> solde;
private LiveData> soldeByDay;
+ private LiveData> pariRembourse;
+
@Inject
public PariViewModel(PariRepository repository){
this.pariRepository = repository;
@@ -57,4 +64,19 @@ public class PariViewModel extends ViewModel {
soldeByDay = pariRepository.getSoldeByDay(agentId, day);
return soldeByDay;
}
+
+ public LiveData> getPariByNumero(String numeroTicket){
+ pariByNumero = pariRepository.getPariByNumero(numeroTicket);
+ return pariByNumero;
+ }
+
+ public LiveData> payerPari(String numeroTicket){
+ pariPaye = pariRepository.payTicket(numeroTicket);
+ return pariPaye;
+ }
+
+ public LiveData> rembourserPari(String numeroTicket){
+ pariRembourse = pariRepository.rembourserTicket(numeroTicket);
+ return pariRembourse;
+ }
}
diff --git a/app/src/main/java/com/example/quiz/viewModel/PointDeVenteViewModel.java b/app/src/main/java/com/example/quiz/viewModel/PointDeVenteViewModel.java
index 137b140..aa5739a 100644
--- a/app/src/main/java/com/example/quiz/viewModel/PointDeVenteViewModel.java
+++ b/app/src/main/java/com/example/quiz/viewModel/PointDeVenteViewModel.java
@@ -17,6 +17,8 @@ public class PointDeVenteViewModel extends ViewModel {
private final PointDeVenteRepository pointDeVenteRepository;
private LiveData>> pointsDeVente;
+ private LiveData> pointDeVenteById;
+
@Inject
public PointDeVenteViewModel(PointDeVenteRepository pointDeVenteRepository){
this.pointDeVenteRepository = pointDeVenteRepository;
@@ -26,4 +28,9 @@ public class PointDeVenteViewModel extends ViewModel {
this.pointsDeVente = pointDeVenteRepository.getPointsDeVente(search);
return this.pointsDeVente;
}
+
+ public LiveData> getPointDeVenteById(String id) {
+ pointDeVenteById = pointDeVenteRepository.getPointDeVenteById(id);
+ return pointDeVenteById;
+ }
}
diff --git a/app/src/main/java/com/example/quiz/viewModel/TpeViewModel.java b/app/src/main/java/com/example/quiz/viewModel/TpeViewModel.java
index 476dc86..9844714 100644
--- a/app/src/main/java/com/example/quiz/viewModel/TpeViewModel.java
+++ b/app/src/main/java/com/example/quiz/viewModel/TpeViewModel.java
@@ -18,6 +18,8 @@ public class TpeViewModel extends ViewModel {
private LiveData> tpeLiveData;
+ private LiveData> tpeByIdLiveData;
+
@Inject
public TpeViewModel(TpeRepository repository){
this.tpeRepository = repository;
@@ -27,4 +29,9 @@ public class TpeViewModel extends ViewModel {
tpeLiveData = tpeRepository.createTpe(tpe);
return tpeLiveData;
}
+
+ public LiveData> getTpeById(String id){
+ tpeByIdLiveData = tpeRepository.getTpeById(id);
+ return tpeByIdLiveData;
+ }
}
diff --git a/app/src/main/res/layout/dialog_error.xml b/app/src/main/res/layout/dialog_error.xml
index ad54b59..9b59dd6 100644
--- a/app/src/main/res/layout/dialog_error.xml
+++ b/app/src/main/res/layout/dialog_error.xml
@@ -1,4 +1,5 @@
+ app:tint="#F44336" />
+ android:outlineSpotShadowColor="#4CAF50"
+ />
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+