ticket fomattage
This commit is contained in:
@@ -90,6 +90,8 @@ dependencies {
|
||||
implementation(libs.material)
|
||||
implementation(libs.constraintlayout)
|
||||
|
||||
implementation(libs.printerlibrary)
|
||||
|
||||
implementation(libs.navigation.fragment)
|
||||
implementation(libs.navigation.ui)
|
||||
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||
|
||||
<uses-permission android:name="com.sunmi.peripheral.printer.permission.PRINTER" />
|
||||
|
||||
<!-- Pour certains modèles -->
|
||||
<uses-permission android:name="android.permission.BIND_PRINTER_SERVICE" />
|
||||
|
||||
|
||||
<!-- ✅ Location Permissions -->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
@@ -40,6 +45,10 @@
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
||||
|
||||
<queries>
|
||||
<package android:name="woyou.aidlservice.jiuiv5" />
|
||||
</queries>
|
||||
|
||||
<application
|
||||
android:name=".PmuHorseBetting"
|
||||
android:allowBackup="true"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.example.quiz;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
@@ -88,10 +89,49 @@ public class AnnulationTicket extends Fragment {
|
||||
binding.annuleTicketBtn.setOnClickListener(v->{
|
||||
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<Result<ParisResponse>>() {
|
||||
viewModel.getPariByNumero(reference).observe(getViewLifecycleOwner(), new Observer<Result<ParisResponse>>() {
|
||||
@Override
|
||||
public void onChanged(Result<ParisResponse> 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<Result<ParisResponse>>() {
|
||||
@Override
|
||||
public void onChanged(Result<ParisResponse> pariResult) {
|
||||
switch (pariResult.status){
|
||||
@@ -113,7 +153,7 @@ public class AnnulationTicket extends Fragment {
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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<MiseInitiale> 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<Boolean> isPrinterReady = new MutableLiveData<>(false);
|
||||
|
||||
SharedPrefsHelper prefsHelper;
|
||||
|
||||
|
||||
private Course course;
|
||||
|
||||
LoaderDialog loader;
|
||||
|
||||
LoaderDialog loader;
|
||||
|
||||
|
||||
private int coeff;
|
||||
@@ -135,7 +146,6 @@ public class BetValidation extends Fragment {
|
||||
PariViewModel pariViewModel;
|
||||
|
||||
|
||||
|
||||
public BetValidation() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
@@ -151,7 +161,15 @@ 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,
|
||||
@@ -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,23 +232,23 @@ 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<String> horses = new ArrayList<>(selectedHorses.getValue());
|
||||
if(horses.size() >= shared.typeOfBet.getValue().getNumberOfHorse() && horse.equals("X")){
|
||||
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")){
|
||||
if (_notClickable(horses) && horse.equals("X")) {
|
||||
Toast.makeText(getContext(), "Vous ne pouvez plus sélectionner X", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
@@ -249,19 +266,19 @@ public class BetValidation extends Fragment {
|
||||
String combinationText = selectedHorses.getValue().stream()
|
||||
.map(h -> h)
|
||||
.collect(Collectors.joining("-"));
|
||||
binding.combination.setText( combinationText);
|
||||
binding.combination.setText(combinationText);
|
||||
});
|
||||
return textView;
|
||||
}
|
||||
|
||||
|
||||
boolean _notClickable(List<String> selectedHorses){
|
||||
boolean _notClickable(List<String> 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<NotifPayload<Course>>(){}.getType();
|
||||
if (shared.selectedCourse.getValue() != null) {
|
||||
stompManager.subscribe("courses/" + shared.selectedCourse.getValue().getId(), json -> {
|
||||
Type type = new TypeToken<NotifPayload<Course>>() {
|
||||
}.getType();
|
||||
NotifPayload<Course> 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<String> 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<String> _getFormule(){
|
||||
List<String> _getFormule() {
|
||||
List<String> combinaison = selectedHorses.getValue();
|
||||
if(!combinaison.contains("X")){
|
||||
if(!order){
|
||||
if (!combinaison.contains("X")) {
|
||||
if (!order) {
|
||||
return List.of("UNITAIRE");
|
||||
}else{
|
||||
} 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,12 +502,9 @@ 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());
|
||||
|
||||
tspl.append("Bamako").append("\n");
|
||||
tspl.append(shared.selectedCourse.getValue().getNom()).append("\n");
|
||||
OffsetDateTime dateTime = OffsetDateTime.parse(shared.selectedCourse.getValue().getHeureDepartPrevue());
|
||||
@@ -519,21 +512,31 @@ public class BetValidation extends Fragment {
|
||||
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();
|
||||
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 = selectedHorses.getValue().stream()
|
||||
.map(String::valueOf)
|
||||
.collect(Collectors.joining("-"));
|
||||
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(printama.lineSeparator()).append("\n");
|
||||
tspl.append("\n").append(sunmiPrinterManager.separationText()).append("\n");
|
||||
tspl.append("MONTANT: ").append(pari.getTypesParisMises().get(0).getMiseTotale()).append(" XOF");
|
||||
tspl.append("\n").append(printama.lineSeparator()).append("\n");
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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<String> 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<String> firstPart = Arrays.stream(numbers).limit(requiredHorse).map(String::valueOf).collect(Collectors.toList());
|
||||
List<String> 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<Result<ParisResponse>>() {
|
||||
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<Result<ParisResponse>>() {
|
||||
@Override
|
||||
public void onChanged(Result<ParisResponse> 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<String> selectedHorses){
|
||||
public void calculateMise(List<String> 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,61 +760,106 @@ 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){
|
||||
if (n == 0) {
|
||||
return f;
|
||||
}
|
||||
for(int i = 1; i <=n; i++){
|
||||
for (int i = 1; i <= n; i++) {
|
||||
f *= i;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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<String, Integer> 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,6 +111,10 @@ public class DerniersParis extends Fragment {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
binding.lastBetsRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
viewModel = new ViewModelProvider(this).get(PariViewModel.class);
|
||||
_getLastBets();
|
||||
}
|
||||
|
||||
void _getLastBets(){
|
||||
viewModel.getDerniersParis(prefsHelper.get("id")).observe(getViewLifecycleOwner(), new Observer<Result<List<ParisResponse>>>() {
|
||||
@Override
|
||||
public void onChanged(Result<List<ParisResponse>> listResult) {
|
||||
@@ -97,9 +128,31 @@ public class DerniersParis extends Fragment {
|
||||
break;
|
||||
case SUCCESS:
|
||||
loader.dismiss();
|
||||
adapter = new LastBetsAdapter(listResult.data, pari -> {
|
||||
});
|
||||
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;
|
||||
}
|
||||
@@ -107,6 +160,154 @@ public class DerniersParis extends Fragment {
|
||||
});
|
||||
}
|
||||
|
||||
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<Result<ParisResponse>>() {
|
||||
@Override
|
||||
public void onChanged(Result<ParisResponse> result) {
|
||||
switch (result.status){
|
||||
case LOADING:
|
||||
loader.show("Annulation du pari");
|
||||
break;
|
||||
case ERROR:
|
||||
loader.dismiss();
|
||||
MessageDialog.showError(getContext(), result.message);
|
||||
break;
|
||||
case SUCCESS:
|
||||
loader.dismiss();
|
||||
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<String> 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<String> 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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<Class<?>> 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() {
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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<Result<TpeResponse>>() {
|
||||
@Override
|
||||
public void onChanged(Result<TpeResponse> 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<Result<PointDeVente>>() {
|
||||
@Override
|
||||
public void onChanged(Result<PointDeVente> 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
|
||||
|
||||
@@ -134,6 +134,10 @@ public class Settings extends Fragment {
|
||||
authNavigator.navigate(agentManagement);
|
||||
}
|
||||
});
|
||||
|
||||
binding.logout.setOnClickListener(v -> {
|
||||
authNavigator.logOut();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<Result<ParisResponse>>() {
|
||||
@Override
|
||||
public void onChanged(Result<ParisResponse> 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<Result<ParisResponse>>() {
|
||||
@Override
|
||||
public void onChanged(Result<ParisResponse> 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<Result<ParisResponse>>() {
|
||||
@Override
|
||||
public void onChanged(Result<ParisResponse> 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
|
||||
|
||||
@@ -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<LastBetsAdapter.LastBetsViewHolder> {
|
||||
|
||||
private List<ParisResponse> 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<ParisResponse> listeParis, OnBetClick onBetClick) {
|
||||
public void setPariClickListener(onPariClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public LastBetsAdapter(List<ParisResponse> 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<ParisResponse> newList) {
|
||||
if (newList == null) {
|
||||
@@ -77,10 +86,44 @@ public class LastBetsAdapter extends RecyclerView.Adapter<LastBetsAdapter.LastBe
|
||||
|
||||
// Mise (défensif)
|
||||
holder.mise.setText("Mise: " + pari.getMiseTotale() + " CFA");
|
||||
holder.tvStatut.setText(pari.getStatutPari() != null ? String.valueOf(pari.getStatutPari()) : "Pas de statut");
|
||||
switch (pari.getStatutPari()){
|
||||
case ANNULE:{
|
||||
holder.tvStatut.setTextColor(Color.RED);
|
||||
holder.btnAnnuler.setVisibility(View.GONE);
|
||||
holder.btnImprimer.setVisibility(View.GONE);
|
||||
break;
|
||||
}
|
||||
case PAYE:{
|
||||
holder.tvStatut.setTextColor(Color.GREEN);
|
||||
holder.btnAnnuler.setVisibility(View.GONE);
|
||||
holder.btnImprimer.setVisibility(View.GONE);
|
||||
break;
|
||||
}
|
||||
case ENREGISTRE:{
|
||||
holder.tvStatut.setTextColor(Color.YELLOW);
|
||||
holder.btnAnnuler.setVisibility(View.VISIBLE);
|
||||
holder.btnImprimer.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
holder.tvStatut.setTextColor(Color.BLACK);
|
||||
holder.btnAnnuler.setVisibility(View.GONE);
|
||||
holder.btnImprimer.setVisibility(View.GONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// click listener défensif
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
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<LastBetsAdapter.LastBe
|
||||
}
|
||||
|
||||
public static class LastBetsViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView betType, horses, course, mise, refenceTicket, typeOfCourse;
|
||||
TextView betType, horses, course, mise, refenceTicket, typeOfCourse, tvStatut;
|
||||
Button btnAnnuler, btnImprimer;;
|
||||
|
||||
public LastBetsViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
@@ -100,6 +144,9 @@ public class LastBetsAdapter extends RecyclerView.Adapter<LastBetsAdapter.LastBe
|
||||
mise = itemView.findViewById(R.id.last_bet_mise);
|
||||
refenceTicket = itemView.findViewById(R.id.reference_ticket);
|
||||
typeOfCourse = itemView.findViewById(R.id.type_of_course);
|
||||
btnAnnuler = itemView.findViewById(R.id.btn_annuler);
|
||||
btnImprimer = itemView.findViewById(R.id.btn_imprimer);
|
||||
tvStatut = itemView.findViewById(R.id.tv_statut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.example.quiz.data.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.List;
|
||||
|
||||
public class ParisResponse implements Serializable {
|
||||
@@ -58,7 +59,10 @@ public class ParisResponse implements Serializable {
|
||||
PAYE,
|
||||
ANNULE,
|
||||
PERDANT,
|
||||
GAGNANT
|
||||
GAGNANT,
|
||||
A_REMBOURSER,
|
||||
REMBOURSE,
|
||||
ECHEC_CACUL
|
||||
}
|
||||
|
||||
// ================= INNER CLASS =================
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.example.quiz.data.model;
|
||||
|
||||
public class ResponseError {
|
||||
private String message;
|
||||
private int status;
|
||||
|
||||
private String timestamp;
|
||||
|
||||
public ResponseError(){
|
||||
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(String timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import retrofit2.converter.gson.GsonConverterFactory;
|
||||
@Module
|
||||
@InstallIn(SingletonComponent.class)
|
||||
public class ApiClient {
|
||||
private static final String BASE_URL = "https://boxer-adapting-bluegill.ngrok-free.app/api/";
|
||||
private static final String BASE_URL = "https://alr.pmu.ml/api/";
|
||||
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -45,9 +45,17 @@ public interface ApiService {
|
||||
@GET("paris/agent/{agentId}/today")
|
||||
Call<List<ParisResponse>> derniersParis(@Path("agentId") String agentId);
|
||||
|
||||
@PATCH("paris/numero/{numeroTicket}/statut")
|
||||
Call<ParisResponse> annulerPari(@Path("numeroTicket") String numeroTicket,
|
||||
@Body() CancelParisPaylaod cancelParisPaylaod);
|
||||
@PATCH("paris/numero/{numeroTicket}/cancel")
|
||||
Call<ParisResponse> annulerPari(@Path("numeroTicket") String numeroTicket);
|
||||
@PATCH("paris/numero/{numeroTicket}/rembourser")
|
||||
Call<ParisResponse> rembourserPari(@Path("numeroTicket") String numeroTicket);
|
||||
|
||||
@PATCH("paris/numero/{numeroTicket}/pay")
|
||||
Call<ParisResponse> payerPari(@Path("numeroTicket") String numeroTicket);
|
||||
|
||||
|
||||
@GET("paris/numero/{numeroTicket}")
|
||||
Call<ParisResponse> getPariByNumero(@Path("numeroTicket") String numeroTicket);
|
||||
|
||||
@GET("paris/agent/{agentId}/solde/course/{courseId}")
|
||||
Call<SoldeResponse> getSoldeByCourse(@Path("agentId") String createdBy, @Path("courseId") String courseId);
|
||||
@@ -58,9 +66,15 @@ public interface ApiService {
|
||||
@POST("terminaux")
|
||||
Call<TpeResponse> createTpe(@Body Tpe tpe);
|
||||
|
||||
@GET("terminaux/{id}")
|
||||
Call<TpeResponse> getTpeById(@Path("id") String id);
|
||||
|
||||
@GET("points-de-vente")
|
||||
Call<PagedModel<PointDeVente>> getPointsDeVente(@Query("nom") String nom);
|
||||
|
||||
@GET("points-de-vente/{id}")
|
||||
Call<PointDeVente> getPointDeVenteById(@Path("id") String id);
|
||||
|
||||
@PATCH("agents/me/pin")
|
||||
Call<User> changePin(@Body ChangePin pin);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<PagedModel<Course>> call, Response<PagedModel<Course>> response) {
|
||||
if(response.isSuccessful()){
|
||||
liveCourses.postValue(Result.success(response.body()));
|
||||
// PagedModel<Course> openedPagesCourses = new PagedModel<>();
|
||||
// List<Course> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<LoginResponse> call, Response<LoginResponse> 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<String, String> errorBody = Collections.emptyMap();
|
||||
if(response.errorBody() != null){
|
||||
errorBody = (Map<String, String>) 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<Result<ParisResponse>> annulerPari(String numeroTicket){
|
||||
public LiveData<Result<ParisResponse>> payTicket(String numeroTicket){
|
||||
MutableLiveData<Result<ParisResponse>> pariResponse = new MutableLiveData<>();
|
||||
pariResponse.setValue(Result.loading());
|
||||
CancelParisPaylaod cancelParisPaylaod = new CancelParisPaylaod("ANNULE");
|
||||
apiService.annulerPari(numeroTicket, cancelParisPaylaod).enqueue(new Callback<ParisResponse>(){
|
||||
apiService.payerPari(numeroTicket).enqueue(new Callback<ParisResponse>(){
|
||||
@Override
|
||||
public void onResponse(Call<ParisResponse> call, Response<ParisResponse> 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<ParisResponse> call, Throwable throwable) {
|
||||
pariResponse.postValue(Result.error(throwable.getMessage()));
|
||||
}
|
||||
});
|
||||
return pariResponse;
|
||||
}
|
||||
|
||||
pariResponse.postValue(Result.error(errorBody));
|
||||
public LiveData<Result<ParisResponse>> rembourserTicket(String numeroTicket){
|
||||
MutableLiveData<Result<ParisResponse>> pariResponse = new MutableLiveData<>();
|
||||
pariResponse.setValue(Result.loading());
|
||||
apiService.rembourserPari(numeroTicket).enqueue(new Callback<ParisResponse>(){
|
||||
@Override
|
||||
public void onResponse(Call<ParisResponse> call, Response<ParisResponse> 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<ParisResponse> call, Throwable throwable) {
|
||||
pariResponse.postValue(Result.error(throwable.getMessage()));
|
||||
}
|
||||
});
|
||||
return pariResponse;
|
||||
}
|
||||
|
||||
public LiveData<Result<ParisResponse>> annulerPari(String numeroTicket){
|
||||
MutableLiveData<Result<ParisResponse>> pariResponse = new MutableLiveData<>();
|
||||
pariResponse.setValue(Result.loading());
|
||||
apiService.annulerPari(numeroTicket).enqueue(new Callback<ParisResponse>(){
|
||||
@Override
|
||||
public void onResponse(Call<ParisResponse> call, Response<ParisResponse> 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<Result<ParisResponse>> getPariByNumero(String numeroTicket) {
|
||||
MutableLiveData<Result<ParisResponse>> pari = new MutableLiveData<>();
|
||||
pari.setValue(Result.loading());
|
||||
apiService.getPariByNumero(numeroTicket).enqueue(new Callback<ParisResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<ParisResponse> call, Response<ParisResponse> 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<ParisResponse> call, Throwable throwable) {
|
||||
pari.postValue(Result.error(throwable.getMessage()));
|
||||
}
|
||||
});
|
||||
return pari;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
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);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errorMessage = e.getMessage();
|
||||
}
|
||||
|
||||
result.postValue(Result.error(errorMessage));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,4 +62,33 @@ public class PointDeVenteRepository {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public LiveData<Result<PointDeVente>> getPointDeVenteById(String id) {
|
||||
MutableLiveData<Result<PointDeVente>> result = new MutableLiveData<>();
|
||||
result.setValue(Result.loading());
|
||||
apiService.getPointDeVenteById(id).enqueue(new Callback<PointDeVente>() {
|
||||
@Override
|
||||
public void onResponse(Call<PointDeVente> call, Response<PointDeVente> 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<PointDeVente> call, Throwable throwable) {
|
||||
result.postValue(Result.error(throwable.getMessage()));
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<TpeResponse> call, Throwable throwable) {
|
||||
tpeLiveData.postValue(Result.error(throwable.getMessage()));
|
||||
}
|
||||
});
|
||||
return tpeLiveData;
|
||||
}
|
||||
|
||||
|
||||
public LiveData<Result<TpeResponse>> getTpeById(String id) {
|
||||
MutableLiveData<Result<TpeResponse>> tpeLiveData = new MutableLiveData<>();
|
||||
tpeLiveData.setValue(Result.loading());
|
||||
apiService.getTpeById(id).enqueue(new Callback<TpeResponse>() {
|
||||
@Override
|
||||
public void onResponse(Call<TpeResponse> call, Response<TpeResponse> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ public class AuthNavigator {
|
||||
return;
|
||||
}
|
||||
if (sessionManager.isExpired()) {
|
||||
if(!dialogIsShowing()){
|
||||
showPinDialog(() -> {
|
||||
sessionManager.updateLastExpiredDate();
|
||||
fragmentManager.beginTransaction()
|
||||
@@ -68,7 +69,7 @@ public class AuthNavigator {
|
||||
.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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,10 @@ public class SessionManager {
|
||||
lastExpiredDate = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public void setToExpire(){
|
||||
lastExpiredDate = null;
|
||||
}
|
||||
|
||||
public boolean isExpired() {
|
||||
if (lastExpiredDate == null) {
|
||||
return true;
|
||||
|
||||
@@ -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<Boolean> 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);
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,17 @@ public class PariViewModel extends ViewModel {
|
||||
|
||||
private LiveData<Result<ParisResponse>> pariAnnule;
|
||||
|
||||
private LiveData<Result<ParisResponse>> pariPaye;
|
||||
|
||||
|
||||
private LiveData<Result<ParisResponse>> pariByNumero;
|
||||
|
||||
private LiveData<Result<SoldeResponse>> solde;
|
||||
|
||||
private LiveData<Result<SoldeResponse>> soldeByDay;
|
||||
|
||||
private LiveData<Result<ParisResponse>> 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<Result<ParisResponse>> getPariByNumero(String numeroTicket){
|
||||
pariByNumero = pariRepository.getPariByNumero(numeroTicket);
|
||||
return pariByNumero;
|
||||
}
|
||||
|
||||
public LiveData<Result<ParisResponse>> payerPari(String numeroTicket){
|
||||
pariPaye = pariRepository.payTicket(numeroTicket);
|
||||
return pariPaye;
|
||||
}
|
||||
|
||||
public LiveData<Result<ParisResponse>> rembourserPari(String numeroTicket){
|
||||
pariRembourse = pariRepository.rembourserTicket(numeroTicket);
|
||||
return pariRembourse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ public class PointDeVenteViewModel extends ViewModel {
|
||||
private final PointDeVenteRepository pointDeVenteRepository;
|
||||
private LiveData<Result<PagedModel<PointDeVente>>> pointsDeVente;
|
||||
|
||||
private LiveData<Result<PointDeVente>> 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<Result<PointDeVente>> getPointDeVenteById(String id) {
|
||||
pointDeVenteById = pointDeVenteRepository.getPointDeVenteById(id);
|
||||
return pointDeVenteById;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ public class TpeViewModel extends ViewModel {
|
||||
|
||||
private LiveData<Result<TpeResponse>> tpeLiveData;
|
||||
|
||||
private LiveData<Result<TpeResponse>> 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<Result<TpeResponse>> getTpeById(String id){
|
||||
tpeByIdLiveData = tpeRepository.getTpeById(id);
|
||||
return tpeByIdLiveData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
@@ -10,7 +11,7 @@
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:src="@android:drawable/ic_delete"
|
||||
android:tint="#F44336"/>
|
||||
app:tint="#F44336" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtMessage"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
@@ -10,7 +11,8 @@
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:src="@android:drawable/checkbox_on_background"
|
||||
android:tint="#4CAF50"/>
|
||||
android:outlineSpotShadowColor="#4CAF50"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtMessage"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
android:textSize="14sp"
|
||||
android:drawableStart="@drawable/hashtag"
|
||||
android:background="@drawable/edittext_outline_white"
|
||||
android:inputType="number"
|
||||
android:inputType="text"
|
||||
/>
|
||||
<ImageButton
|
||||
android:id="@+id/scan_ticket_btn"
|
||||
|
||||
@@ -54,20 +54,20 @@
|
||||
android:text="ANNULER TICKET"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="#FFFFFF"/>
|
||||
<Button
|
||||
android:id="@+id/report_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="57dp"
|
||||
android:textSize="21sp"
|
||||
android:textAlignment="textStart"
|
||||
android:layout_marginVertical="4sp"
|
||||
android:background="@drawable/rounded_button_green"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:backgroundTint="@color/primary_green"
|
||||
android:drawableLeft="@drawable/tpe"
|
||||
android:text="RAPPORTS"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="#FFFFFF"/>
|
||||
<!-- <Button-->
|
||||
<!-- android:id="@+id/report_btn"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="57dp"-->
|
||||
<!-- android:textSize="21sp"-->
|
||||
<!-- android:textAlignment="textStart"-->
|
||||
<!-- android:layout_marginVertical="4sp"-->
|
||||
<!-- android:background="@drawable/rounded_button_green"-->
|
||||
<!-- android:fontFamily="sans-serif-medium"-->
|
||||
<!-- android:backgroundTint="@color/primary_green"-->
|
||||
<!-- android:drawableLeft="@drawable/tpe"-->
|
||||
<!-- android:text="RAPPORTS"-->
|
||||
<!-- android:textAllCaps="false"-->
|
||||
<!-- android:textColor="#FFFFFF"/>-->
|
||||
<Button
|
||||
android:id="@+id/last_bets_btn"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
android:textColor="#FFFFFF"/>
|
||||
<Button
|
||||
android:id="@+id/settings"
|
||||
android:tag="@id/tag_pin_exempt"
|
||||
android:tag="tag_pin_exempt"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="57dp"
|
||||
android:textSize="23sp"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -212,23 +213,28 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="30sp"
|
||||
android:gravity="center">
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel"
|
||||
android:layout_width="200dp"
|
||||
android:layout_marginRight="3sp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@color/primary_red"
|
||||
android:text="@string/cancel"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/validate"
|
||||
android:layout_marginLeft="3sp"
|
||||
android:layout_width="200dp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="@color/primary_green"
|
||||
android:text="@string/validate"/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</FrameLayout>
|
||||
|
||||
@@ -12,19 +12,19 @@
|
||||
android:gravity="start"
|
||||
android:orientation="vertical"
|
||||
android:visibility="visible">
|
||||
<Button
|
||||
android:id="@+id/agent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:textSize="21sp"
|
||||
android:textAlignment="center"
|
||||
android:layout_marginVertical="4sp"
|
||||
android:background="@drawable/rounded_button_green"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:backgroundTint="@color/primary_green"
|
||||
android:text="@string/agents_setting"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="#FFFFFF"/>
|
||||
<!-- <Button-->
|
||||
<!-- android:id="@+id/agent"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="60dp"-->
|
||||
<!-- android:textSize="21sp"-->
|
||||
<!-- android:textAlignment="center"-->
|
||||
<!-- android:layout_marginVertical="4sp"-->
|
||||
<!-- android:background="@drawable/rounded_button_green"-->
|
||||
<!-- android:fontFamily="sans-serif-medium"-->
|
||||
<!-- android:backgroundTint="@color/primary_green"-->
|
||||
<!-- android:text="@string/agents_setting"-->
|
||||
<!-- android:textAllCaps="false"-->
|
||||
<!-- android:textColor="#FFFFFF"/>-->
|
||||
<Button
|
||||
android:id="@+id/change_pin"
|
||||
android:layout_width="match_parent"
|
||||
@@ -40,6 +40,7 @@
|
||||
android:textColor="#FFFFFF"/>
|
||||
<Button
|
||||
android:id="@+id/server_config"
|
||||
android:tag="tag_pin_exempt"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:textSize="21sp"
|
||||
@@ -66,6 +67,7 @@
|
||||
android:textColor="#FFFFFF"/>
|
||||
<Button
|
||||
android:id="@+id/logs"
|
||||
android:tag="tag_pin_exempt"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:textSize="21sp"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
android:textSize="14sp"
|
||||
android:drawableStart="@drawable/hashtag"
|
||||
android:background="@drawable/edittext_outline_white"
|
||||
android:inputType="number"
|
||||
android:inputType="text"
|
||||
/>
|
||||
<ImageButton
|
||||
android:id="@+id/scan_ticket_btn"
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
android:padding="18dp"
|
||||
android:background="@drawable/course_item_border">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="center_vertical">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_gravity="start">
|
||||
<ImageView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
@@ -24,14 +24,15 @@
|
||||
</ImageView>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/tvName"
|
||||
android:text="GP SANGARE"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="18sp"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/white"
|
||||
android:textFontWeight="500"
|
||||
android:fontFamily="sans-serif-medium">
|
||||
|
||||
@@ -2,18 +2,30 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:padding="8dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp">
|
||||
android:gravity="end">
|
||||
<TextView
|
||||
android:id="@+id/tv_statut"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Statut"
|
||||
android:textSize="20sp">
|
||||
</TextView>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Première ligne : Course et Type -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/last_bet_course"
|
||||
@@ -21,14 +33,13 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Course: 5"
|
||||
android:textSize="16sp"
|
||||
android:gravity="start"
|
||||
android:padding="4dp" />
|
||||
android:textSize="14sp"
|
||||
android:padding="2dp" />
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
app:dividerColor="@color/black" />
|
||||
|
||||
<TextView
|
||||
@@ -37,24 +48,18 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="QUARTE + TIERCE"
|
||||
android:textSize="16sp"
|
||||
android:textSize="12sp"
|
||||
android:gravity="end"
|
||||
android:padding="4dp" />
|
||||
|
||||
android:padding="2dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
app:dividerColor="@color/black"/>
|
||||
|
||||
<!-- Deuxième ligne : Référence et Type de pari -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginBottom="3dp">
|
||||
android:layout_marginTop="2dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/reference_ticket"
|
||||
@@ -62,14 +67,13 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="12573829288"
|
||||
android:textSize="16sp"
|
||||
android:gravity="start"
|
||||
android:padding="4dp" />
|
||||
android:textSize="12sp"
|
||||
android:padding="2dp" />
|
||||
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:layout_height="16dp"
|
||||
android:layout_marginHorizontal="4dp"
|
||||
app:dividerColor="@color/black" />
|
||||
|
||||
<TextView
|
||||
@@ -78,25 +82,70 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="TIERCE"
|
||||
android:textSize="16sp"
|
||||
android:textFontWeight="900"
|
||||
android:textSize="13sp"
|
||||
android:textStyle="bold"
|
||||
android:gravity="end"
|
||||
android:padding="4dp" />
|
||||
|
||||
android:padding="2dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Troisième ligne : Chevaux et Mise -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginTop="2dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/last_bet_horses"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Horses: 3-7-9"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginTop="4dp"/>
|
||||
android:textSize="13sp"
|
||||
android:padding="2dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/last_bet_mise"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Mise: 500 CFA"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginTop="4dp"/>
|
||||
android:textSize="13sp"
|
||||
android:padding="2dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Séparateur avant le dropdown -->
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginVertical="6dp"
|
||||
app:dividerColor="@color/black" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_annuler"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/rounded_button_red"
|
||||
android:text="Annuler" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_imprimer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="@drawable/rounded_button_green"
|
||||
android:text="Imprimer" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
283
app/src/main/res/layout/pay_confirmation_layout.xml
Normal file
283
app/src/main/res/layout/pay_confirmation_layout.xml
Normal file
@@ -0,0 +1,283 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
app:cardElevation="8dp"
|
||||
app:cardBackgroundColor="@android:color/white">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<!-- En-tête avec statut -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_statut"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Statut: ENREGISTRÉ"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_date_heure"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Date et heure"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/colorAccent" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Séparateur -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/login_background"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Numéro de la course -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Numéro course :"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_numero_course"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="5"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/primary_green" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Nom de la course -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Nom course :"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_nom_course"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Prix de l'Arc de Triomphe"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/primary_green" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Numéro Ticket -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="N° Ticket :"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_numero_ticket"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="T-2024-001234"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/primary_green"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Date de prise -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Date prise :"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_date_prise"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="15/03/2024 14:30"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/primary_green" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Combinaison -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Combinaison :"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_combinaison"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="5 - 8 - 12 - 15"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/primary_green"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/notes_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone"
|
||||
android:layout_marginBottom="12sp"
|
||||
android:layout_gravity="start">
|
||||
<TextView
|
||||
android:id="@+id/notes"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="2 ordres, 6 desordres"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/primary_green"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Montant -->
|
||||
<LinearLayout
|
||||
android:id="@+id/tv_montant_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="20dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Montant :"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_montant"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="1 000 FCFA"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/primary_green" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Séparateur -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/background_gray"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Message dynamique selon statut -->
|
||||
<TextView
|
||||
android:id="@+id/tv_message_statut"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Veuillez confirmer l'enregistrement de ce pari"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/primary_green"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:padding="5dp"
|
||||
android:background="@color/green_opacity_30"
|
||||
android:visibility="visible" />
|
||||
|
||||
<!-- Boutons Confirmer et Annuler -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_annuler"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="Annuler"
|
||||
android:textSize="14sp"
|
||||
app:cornerRadius="8dp"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_confirmer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="Confirmer"
|
||||
android:textSize="14sp"
|
||||
app:cornerRadius="8dp"
|
||||
style="@style/Widget.Material3.Button" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
@@ -4,4 +4,9 @@
|
||||
<item>Espèce</item>
|
||||
<item>Orange Money</item>
|
||||
</string-array>
|
||||
<string-array name="action_options">
|
||||
<item>Imprimer</item>
|
||||
<item>Annuler</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
@@ -14,6 +14,7 @@ navigationUi = "2.6.0"
|
||||
googleAndroidLibrariesMapsplatformSecretsGradlePlugin = "2.0.1"
|
||||
okhttp = "4.12.0"
|
||||
playServicesMaps = "18.1.0"
|
||||
printerlibrary = "1.0.23"
|
||||
recyclerviewV7 = "28.0.0"
|
||||
retrofit = "2.11.0"
|
||||
rxandroid = "1.2.1"
|
||||
@@ -55,6 +56,7 @@ navigation-fragment = { group = "androidx.navigation", name = "navigation-fragme
|
||||
navigation-ui = { group = "androidx.navigation", name = "navigation-ui", version.ref = "navigationUi" }
|
||||
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
|
||||
play-services-maps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" }
|
||||
printerlibrary = { module = "com.sunmi:printerlibrary", version.ref = "printerlibrary" }
|
||||
recyclerview-v7 = { module = "com.android.support:recyclerview-v7", version.ref = "recyclerviewV7" }
|
||||
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
|
||||
room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomCommonJvm" }
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.anggastudio.printama.constants.PW;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Printama is a lightweight Android library for printing text and bitmaps to ESC/POS Bluetooth
|
||||
@@ -280,6 +281,8 @@ public class Printama {
|
||||
Pref.setBoolean(Pref.IS_PRINTER_3INCH, is3inches);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static boolean is3inchesPrinter() {
|
||||
return Pref.getBoolean(Pref.IS_PRINTER_3INCH);
|
||||
}
|
||||
@@ -311,11 +314,27 @@ public class Printama {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public int checkPaperStatus(){
|
||||
return _util.checkPaperStatus();
|
||||
public void testAllPaperStatusCommands(){
|
||||
_printama.connect(printama -> {
|
||||
_util.testAllPaperStatusCommands();
|
||||
});
|
||||
}
|
||||
|
||||
public void checkPaperStatus(Consumer<String> status){
|
||||
_printama.connect(printama -> {
|
||||
String paperStatus = _util.checkPaperStatus();
|
||||
status.accept(paperStatus);
|
||||
});
|
||||
}
|
||||
|
||||
public void isQueued(Consumer<Integer> status){
|
||||
_printama.connect(printama -> {
|
||||
int isQueued = _util.isQueued();
|
||||
status.accept(isQueued);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public boolean isConnected() {
|
||||
return _util.isConnected();
|
||||
}
|
||||
@@ -361,34 +380,48 @@ public class Printama {
|
||||
}
|
||||
|
||||
|
||||
public void printTextBuilder(StringBuilder text, Bitmap bitmap, String numeroTicket,Bitmap barCode){
|
||||
|
||||
public void printTextBuilder(StringBuilder text, Bitmap bitmap, String numeroTicket, Bitmap barCode, PrintCallback callback) {
|
||||
_printama.connect(printama -> {
|
||||
try {
|
||||
_util.resetPrinter();
|
||||
_util.setBold();
|
||||
_util.printImage(bitmap);
|
||||
_util.printText(printama.lineSeparator()+"\n");
|
||||
_util.printText(printama.lineSeparator() + "\n");
|
||||
_util.setBold();
|
||||
_util.printImage(barCode);
|
||||
_util.setBold();
|
||||
_util.setNormalText();
|
||||
_util.setAlign(PA.CENTER);
|
||||
_util.printText(numeroTicket);
|
||||
_util.printText("\n"+printama.lineSeparator()+"\n");
|
||||
_util.printText("\n" + printama.lineSeparator() + "\n");
|
||||
_util.setBold();
|
||||
_util.setNormalText();
|
||||
_util.setAlign(0);
|
||||
_util.setAlign(PA.LEFT);
|
||||
_util.printText(text.toString());
|
||||
_util.printText(printama.lineSeparator()+"\n");
|
||||
_util.printText(printama.lineSeparator() + "\n");
|
||||
_util.setBold();
|
||||
_util.setNormalText();
|
||||
_util.setAlign(PA.CENTER);
|
||||
_util.printText("Powered by PMU-MALI");
|
||||
_util.printText("\n"+printama.lineSeparator()+"\n");
|
||||
_util.printText("\n" + printama.lineSeparator() + "\n");
|
||||
_util.printText("\n\n\n");
|
||||
printama.feedPaper();
|
||||
printama.close();
|
||||
});
|
||||
if (callback != null) callback.onResult(true, null);
|
||||
} catch (Exception e) {
|
||||
if (callback != null) callback.onResult(false, e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, error -> {
|
||||
if (callback != null) callback.onResult(false, error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public interface PrintCallback{
|
||||
void onResult(boolean success, String errorMessage);
|
||||
}
|
||||
|
||||
public void printSold(Bitmap bitmap, String title, StringBuilder text){
|
||||
@@ -554,7 +587,19 @@ public class Printama {
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
public void printText(String text) {
|
||||
printText(text, PA.LEFT);
|
||||
_printama.connect((printama)->{
|
||||
_util.printText(text);
|
||||
});
|
||||
}
|
||||
|
||||
public void myPrintText(String text, Consumer<String> callback) {
|
||||
_printama.connect(printama -> {
|
||||
if(_util.printText(text)){
|
||||
callback.accept("L'impression a été effectuée avec succès");
|
||||
}else{
|
||||
callback.accept("L'impression a échoué");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -708,6 +753,8 @@ public class Printama {
|
||||
return spaces.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
// COLUMN FORMATTERS
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -144,12 +144,25 @@ class PrinterUtil {
|
||||
String s = StrUtil.encodeNonAscii(text);
|
||||
btOutputStream.write(s.getBytes());
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String textTest(String text){
|
||||
try{
|
||||
String s = StrUtil.encodeNonAscii(text);
|
||||
btOutputStream.write(s.getBytes());
|
||||
btOutputStream.flush();
|
||||
int available = btInputStream.available();
|
||||
return String.valueOf(available);
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
return "Erreur: "+e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
boolean printTextBuilder(StringBuilder text){
|
||||
try {
|
||||
String tspl = ""+ text + "\r\n";
|
||||
@@ -162,6 +175,61 @@ class PrinterUtil {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Vérifie si l'imprimante a une opération en attente ou en cours
|
||||
*
|
||||
* @return
|
||||
* 0 = Aucune opération (imprimante prête)
|
||||
* 1 = Opération en cours d'impression
|
||||
* 2 = Opération en attente (buffer plein)
|
||||
* -1 = Erreur / impossible de déterminer
|
||||
*/
|
||||
public int isQueued() {
|
||||
try {
|
||||
// Vider le buffer d'entrée avant d'envoyer la commande
|
||||
while (btInputStream != null && btInputStream.available() > 0) {
|
||||
btInputStream.read();
|
||||
}
|
||||
// Commande DLE EOT 1 - Statut en temps réel
|
||||
byte[] command = new byte[]{0x10, 0x04, 0x01};
|
||||
btOutputStream.write(command);
|
||||
btOutputStream.flush();
|
||||
|
||||
// Attendre 100ms pour la réponse
|
||||
Thread.sleep(100);
|
||||
|
||||
// Lire la réponse (1 octet)
|
||||
if (btInputStream != null && btInputStream.available() > 0) {
|
||||
byte[] response = new byte[1];
|
||||
int bytesRead = btInputStream.read(response);
|
||||
|
||||
if (bytesRead > 0) {
|
||||
byte status = response[0];
|
||||
|
||||
// Bit 1 (0x02) = Imprimante en cours d'impression
|
||||
if ((status & 0x02) != 0) {
|
||||
return 1; // Opération en cours
|
||||
}
|
||||
|
||||
// Bit 3 (0x08) = Buffer plein / attente
|
||||
if ((status & 0x08) != 0) {
|
||||
return 2; // Opération en attente
|
||||
}
|
||||
|
||||
return 0; // Aucune opération
|
||||
}
|
||||
}
|
||||
|
||||
// Pas de réponse
|
||||
return -1;
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Erreur isQueued: " + e.getMessage());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void setNormalizedForAll(){
|
||||
printUnicode(NORMALIZED_FOR_ALL);
|
||||
}
|
||||
@@ -265,39 +333,190 @@ class PrinterUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public int checkPaperStatus() {
|
||||
public void testAllPaperStatusCommands() {
|
||||
// Liste des commandes à tester
|
||||
int[][] commands = {
|
||||
{0x1D, 0x72, 0x01}, // GS r 1 - Standard paper status
|
||||
{0x10, 0x04, 0x01}, // DLE EOT 1 - Real-time status
|
||||
{0x10, 0x04, 0x04}, // DLE EOT 4 - Paper sensor status
|
||||
{0x1B, 0x76, 0x00}, // ESC v 0 - Paper sensor
|
||||
{0x1D, 0x61, 0x01}, // GS a 1 - Enable real-time mode
|
||||
{0x1D, 0x49, 0x01}, // GS I 1 - Printer ID
|
||||
{0x1B, 0x69, 0x00} // ESC i 0 - Printer status
|
||||
};
|
||||
|
||||
for (int i = 0; i < commands.length; i++) {
|
||||
try {
|
||||
// Certaines imprimantes doivent être en mode "real-time"
|
||||
// Commande GS a 1 pour activer le mode "real-time"
|
||||
byte[] realtimeMode = new byte[]{0x1D, 0x61, 0x01};
|
||||
btOutputStream.write(realtimeMode);
|
||||
btOutputStream.flush();
|
||||
Log.e("TEST", "========================================");
|
||||
Log.e("TEST", "Test commande " + i + ": " + bytesToHex(commands[i]));
|
||||
|
||||
Thread.sleep(50);
|
||||
|
||||
// Ensuite la commande de statut
|
||||
byte[] statusCommand = new byte[]{0x1D, 0x72, 0x01};
|
||||
btOutputStream.write(statusCommand);
|
||||
btOutputStream.flush();
|
||||
|
||||
Thread.sleep(200);
|
||||
|
||||
// Lire la réponse
|
||||
byte[] response = new byte[4];
|
||||
int bytesRead = btInputStream.read(response);
|
||||
|
||||
if (bytesRead > 0) {
|
||||
// Traiter la réponse...
|
||||
return 0;
|
||||
// Nettoyer buffer
|
||||
while (btInputStream.available() > 0) {
|
||||
btInputStream.read();
|
||||
}
|
||||
|
||||
return -1;
|
||||
// Envoyer commande
|
||||
byte[] cmd = new byte[commands[i].length];
|
||||
for (int j = 0; j < commands[i].length; j++) {
|
||||
cmd[j] = (byte) commands[i][j];
|
||||
}
|
||||
btOutputStream.write(cmd);
|
||||
btOutputStream.flush();
|
||||
|
||||
// Attendre réponse
|
||||
Thread.sleep(300);
|
||||
|
||||
// Lire réponse
|
||||
byte[] response = new byte[16];
|
||||
int totalRead = 0;
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
while (totalRead < response.length && System.currentTimeMillis() - startTime < 1000) {
|
||||
if (btInputStream.available() > 0) {
|
||||
int read = btInputStream.read(response, totalRead, response.length - totalRead);
|
||||
if (read > 0) {
|
||||
totalRead += read;
|
||||
}
|
||||
}
|
||||
Thread.sleep(20);
|
||||
}
|
||||
|
||||
if (totalRead > 0) {
|
||||
Log.e("TEST", "✓ RÉPONSE REÇUE ! " + totalRead + " octets");
|
||||
StringBuilder hex = new StringBuilder();
|
||||
for (int j = 0; j < totalRead; j++) {
|
||||
hex.append(String.format("%02X ", response[j]));
|
||||
}
|
||||
Log.e("TEST", " Hex: " + hex.toString());
|
||||
|
||||
// Interpréter la réponse selon la commande
|
||||
if (i == 0 && totalRead >= 1) { // GS r 1
|
||||
interpretGS_r1(response[0]);
|
||||
} else if (i == 1 && totalRead >= 1) { // DLE EOT 1
|
||||
interpretDLE_EOT_1(response[0]);
|
||||
} else if (i == 2 && totalRead >= 1) { // DLE EOT 4
|
||||
interpretDLE_EOT_4(response[0]);
|
||||
} else if (i == 5 && totalRead >= 1) { // GS I 1
|
||||
Log.e("TEST", " ID Imprimante: " + new String(response, 0, totalRead));
|
||||
}
|
||||
} else {
|
||||
Log.e("TEST", "✗ AUCUNE RÉPONSE");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("TEST", "Erreur commande " + i, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void interpretGS_r1(byte status) {
|
||||
Log.e("TEST", "Interprétation GS r 1:");
|
||||
Log.e("TEST", " Bit 0 (couvercle): " + ((status & 0x01) != 0 ? "OUVERT" : "FERMÉ"));
|
||||
Log.e("TEST", " Bit 2 (papier): " + ((status & 0x04) != 0 ? "FAIBLE" : "OK"));
|
||||
Log.e("TEST", " Bit 5 (papier): " + ((status & 0x20) != 0 ? "VIDE" : "OK"));
|
||||
}
|
||||
|
||||
private void interpretDLE_EOT_1(byte status) {
|
||||
Log.e("TEST", "Interprétation DLE EOT 1:");
|
||||
Log.e("TEST", " Bit 2 (papier): " + ((status & 0x04) != 0 ? "VIDE" : "OK"));
|
||||
}
|
||||
|
||||
private void interpretDLE_EOT_4(byte status) {
|
||||
Log.e("TEST", "Interprétation DLE EOT 4:");
|
||||
Log.e("TEST", " Bit 0 (couvercle): " + ((status & 0x01) != 0 ? "OUVERT" : "FERMÉ"));
|
||||
Log.e("TEST", " Bit 2 (papier): " + ((status & 0x04) != 0 ? "FAIBLE" : "OK"));
|
||||
Log.e("TEST", " Bit 5 (papier): " + ((status & 0x20) != 0 ? "VIDE" : "OK"));
|
||||
}
|
||||
|
||||
private String bytesToHex(int[] bytes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int b : bytes) {
|
||||
sb.append(String.format("%02X ", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getPrinterPaperStatus() {
|
||||
try{
|
||||
byte[] command = new byte[]{0x10, 0x04, 0x04};
|
||||
btOutputStream.write(command);
|
||||
btOutputStream.flush();
|
||||
Thread.sleep(300);
|
||||
int status = btInputStream.read();
|
||||
return String.valueOf(status);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String checkPaperStatus() {
|
||||
try {
|
||||
// 1. Envoyer la commande d'activation ASB
|
||||
byte[] cmd = {0x1D, 0x61, (byte) 0xFF};
|
||||
btOutputStream.write(cmd);
|
||||
btOutputStream.flush();
|
||||
|
||||
// 2. Attendre un peu plus longtemps pour la réponse
|
||||
Thread.sleep(500);
|
||||
|
||||
// 3. Lire tout ce qui est disponible dans le buffer
|
||||
int available = btInputStream.available();
|
||||
if (available > 0) {
|
||||
byte[] buffer = new byte[available];
|
||||
btInputStream.read(buffer);
|
||||
|
||||
// On convertit le buffer en une chaîne lisible (Hex)
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : buffer) {
|
||||
sb.append(String.format("%02X ", b));
|
||||
}
|
||||
return "Status: " + sb.toString();
|
||||
} else {
|
||||
return "0 (Aucune réponse)";
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return "Erreur: " + e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int readStatusByte(int timeoutMs) throws IOException, InterruptedException {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
// petite attente initiale (important en Bluetooth)
|
||||
Thread.sleep(50);
|
||||
|
||||
while (System.currentTimeMillis() - start < timeoutMs) {
|
||||
|
||||
int available = btInputStream.available();
|
||||
Log.e("AVAILABLE", "STATUS: "+String.valueOf(available) );
|
||||
if (available > 0) {
|
||||
byte[] buffer = new byte[available];
|
||||
int read = btInputStream.read(buffer);
|
||||
if (read > 0) {
|
||||
int value = buffer[0] & 0xFF;
|
||||
|
||||
Log.d("Printama", "Raw bytes: " + bytesToHex(buffer, read));
|
||||
|
||||
return value; // on prend le premier byte
|
||||
}
|
||||
}
|
||||
|
||||
Thread.sleep(20);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private String bytesToHex(byte[] bytes, int length) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
sb.append(String.format("%02X ", bytes[i]));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
boolean printImage(Bitmap bitmap, int width) {
|
||||
return printImage(PA.CENTER, bitmap, width);
|
||||
|
||||
Reference in New Issue
Block a user