feat: Codigo fuente SIO Mobile - App Android para Operadores
Aplicacion movil Android para el sistema SIO (Sistema Integral de Operaciones) de Drenax. Permite a los operadores gestionar sus servicios diarios. Funcionalidades principales: - Login y autenticacion JWT - Checklist de vehiculos - Gestion de jornada laboral - Lista de servicios asignados - Captura de evidencias fotograficas - Firma digital del cliente - Encuestas de satisfaccion - Notificaciones push (Firebase) - Almacenamiento offline (ObjectBox) - Geolocalizacion y mapas Stack tecnologico: - Kotlin - Android SDK 33 - Retrofit + OkHttp - ObjectBox - Firebase (FCM, Crashlytics, Analytics) - Google Maps Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
75
.gitignore
vendored
Normal file
75
.gitignore
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
*.aab
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
out/
|
||||
release/
|
||||
|
||||
# Gradle files
|
||||
.gradle/
|
||||
build/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
|
||||
# Log Files
|
||||
*.log
|
||||
|
||||
# Android Studio Navigation editor temp files
|
||||
.navigation/
|
||||
|
||||
# Android Studio captures folder
|
||||
captures/
|
||||
|
||||
# IntelliJ
|
||||
*.iml
|
||||
*.idea
|
||||
|
||||
# Keystore files
|
||||
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||
#*.jks
|
||||
#*.keystore
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
.externalNativeBuild
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
# google-services.json
|
||||
|
||||
# Freeline
|
||||
freeline.py
|
||||
freeline/
|
||||
freeline_project_description.json
|
||||
|
||||
# fastlane
|
||||
fastlane/report.xml
|
||||
fastlane/Preview.html
|
||||
fastlane/screenshots
|
||||
fastlane/test_output
|
||||
fastlane/readme.md
|
||||
|
||||
# Version control
|
||||
vcs.xml
|
||||
|
||||
# lint
|
||||
lint/intermediates/
|
||||
lint/generated/
|
||||
lint/outputs/
|
||||
lint/tmp/
|
||||
# lint/reports/
|
||||
|
||||
# OS X
|
||||
.DS_STORE
|
||||
663
README.md
Normal file
663
README.md
Normal file
@@ -0,0 +1,663 @@
|
||||
# SIO Mobile - Aplicacion Android para Operadores
|
||||
|
||||
## Drenax - Sistema Integral de Operaciones
|
||||
|
||||
---
|
||||
|
||||
## Informacion General
|
||||
|
||||
| Campo | Valor |
|
||||
|-------|-------|
|
||||
| Nombre App | SIO Drenax |
|
||||
| Package ID | com.iesoluciones.siodrenax |
|
||||
| Version | 1.00 (versionCode: 3) |
|
||||
| Plataforma | Android |
|
||||
| SDK Minimo | 28 (Android 9.0 Pie) |
|
||||
| SDK Target | 33 (Android 13) |
|
||||
| Lenguaje | Kotlin |
|
||||
|
||||
---
|
||||
|
||||
## Arquitectura del Sistema
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ APP MOVIL │
|
||||
│ Android (Kotlin) │
|
||||
│ com.iesoluciones.siodrenax │
|
||||
└─────────────────────┬───────────────────────────────────┘
|
||||
│ HTTPS (REST API)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ BACKEND │
|
||||
│ Laravel 5.5 (PHP 7.4) │
|
||||
│ https://sio-api.consultoria-as.com │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Estructura del Proyecto
|
||||
|
||||
```
|
||||
SIO-Mobile/
|
||||
├── app/
|
||||
│ ├── build.gradle # Configuracion de compilacion
|
||||
│ └── src/
|
||||
│ └── main/
|
||||
│ ├── AndroidManifest.xml # Configuracion de la app
|
||||
│ ├── java/com/iesoluciones/siodrenax/
|
||||
│ │ ├── activities/ # Pantallas de la app
|
||||
│ │ │ ├── SplashActivity.kt
|
||||
│ │ │ ├── LoginActivity.kt
|
||||
│ │ │ ├── WorkdayActivity.kt
|
||||
│ │ │ ├── OrdersActivity.kt
|
||||
│ │ │ ├── OrderDetailActivity.kt
|
||||
│ │ │ ├── OrderProgressActivity.kt
|
||||
│ │ │ ├── CameraActivity.kt
|
||||
│ │ │ ├── SignatureActivity.kt
|
||||
│ │ │ ├── SurveyActivity.kt
|
||||
│ │ │ └── ConfirmationActivity.kt
|
||||
│ │ ├── adapters/ # Adaptadores RecyclerView
|
||||
│ │ ├── entities/ # Entidades ObjectBox (DB local)
|
||||
│ │ ├── interfaces/ # Interfaces
|
||||
│ │ ├── models/ # Modelos de datos
|
||||
│ │ ├── network/ # Configuracion API (Retrofit)
|
||||
│ │ ├── services/ # Servicios (notificaciones)
|
||||
│ │ │ └── NotificationService.kt
|
||||
│ │ └── utils/ # Utilidades
|
||||
│ └── res/ # Recursos
|
||||
│ ├── layout/ # Layouts XML
|
||||
│ ├── values/ # Strings, colors, styles
|
||||
│ ├── drawable/ # Iconos e imagenes
|
||||
│ └── mipmap/ # Iconos de app
|
||||
├── gradle/
|
||||
├── mylibrary/ # Libreria auxiliar
|
||||
├── build.gradle # Configuracion proyecto
|
||||
├── settings.gradle
|
||||
└── google-services.json # Configuracion Firebase
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pantallas de la Aplicacion
|
||||
|
||||
| Activity | Descripcion |
|
||||
|----------|-------------|
|
||||
| SplashActivity | Pantalla de inicio/carga |
|
||||
| LoginActivity | Inicio de sesion |
|
||||
| WorkdayActivity | Inicio/fin de jornada laboral |
|
||||
| OrdersActivity | Lista de servicios asignados |
|
||||
| OrderDetailActivity | Detalle de un servicio |
|
||||
| OrderProgressActivity | Progreso del servicio |
|
||||
| CameraActivity | Captura de fotografias |
|
||||
| SignatureActivity | Captura de firma del cliente |
|
||||
| SurveyActivity | Encuestas de satisfaccion |
|
||||
| ConfirmationActivity | Confirmacion de servicio |
|
||||
| NextServiceActivity | Servicios del dia siguiente |
|
||||
| PdfViewerActivity | Visualizador de PDF |
|
||||
| OperatorsActivity | Lista de operadores (supervisor) |
|
||||
| WorkdayManagerActivity | Gestion de jornada (supervisor) |
|
||||
| OrdersManagerActivity | Gestion de ordenes (supervisor) |
|
||||
| HerramientaSurveyActivity | Encuesta de herramientas |
|
||||
| MaterialSurveyActivity | Encuesta de materiales |
|
||||
| RevisionSurveyActivity | Encuesta de revision |
|
||||
|
||||
---
|
||||
|
||||
## Flujos de la Aplicacion
|
||||
|
||||
### Flujo Operador
|
||||
|
||||
```
|
||||
1. Splash Screen
|
||||
↓
|
||||
2. Login (credenciales)
|
||||
↓
|
||||
3. Checklist Vehiculo
|
||||
↓
|
||||
4. Iniciar Jornada
|
||||
├── Seleccionar vehiculo
|
||||
├── Registrar kilometraje inicial
|
||||
└── Capturar ubicacion GPS
|
||||
↓
|
||||
5. Ver Lista de Servicios del Dia
|
||||
↓
|
||||
6. Seleccionar Servicio
|
||||
↓
|
||||
7. Ver Detalle del Servicio
|
||||
├── Informacion del cliente
|
||||
├── Direccion (con mapa)
|
||||
├── Tipo de servicio
|
||||
└── Observaciones
|
||||
↓
|
||||
8. Iniciar Servicio
|
||||
└── Registra ubicacion GPS
|
||||
↓
|
||||
9. Realizar Trabajo
|
||||
↓
|
||||
10. Capturar Evidencias
|
||||
├── Foto antes
|
||||
├── Foto durante
|
||||
└── Foto despues
|
||||
↓
|
||||
11. Encuestas
|
||||
├── Herramientas utilizadas
|
||||
├── Materiales empleados
|
||||
└── Revision general
|
||||
↓
|
||||
12. Capturar Firma del Cliente
|
||||
↓
|
||||
13. Finalizar Servicio
|
||||
├── Registrar litraje
|
||||
└── Comentarios
|
||||
↓
|
||||
14. Siguiente Servicio o Fin de Jornada
|
||||
├── Mas servicios → Paso 6
|
||||
└── Fin jornada → Registrar kilometraje final
|
||||
```
|
||||
|
||||
### Flujo Supervisor
|
||||
|
||||
```
|
||||
1. Login
|
||||
↓
|
||||
2. Iniciar Jornada Supervisor
|
||||
↓
|
||||
3. Ver Lista de Operadores
|
||||
↓
|
||||
4. Seleccionar Operador
|
||||
↓
|
||||
5. Ver Servicios del Operador
|
||||
├── Estatus de cada servicio
|
||||
├── Ubicacion actual
|
||||
└── Progreso del dia
|
||||
↓
|
||||
6. Monitorear en Tiempo Real
|
||||
↓
|
||||
7. Fin de Jornada
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuracion de API
|
||||
|
||||
### URLs de Conexion
|
||||
|
||||
```kotlin
|
||||
// En app/build.gradle - buildTypes
|
||||
|
||||
// Produccion
|
||||
buildConfigField("String", "BASE_URL", '"https://sio-api.consultoria-as.com/api/"')
|
||||
buildConfigField("String", "STORAGE_URL", '"https://sio-api.consultoria-as.com/storage/"')
|
||||
|
||||
// Desarrollo (opcional)
|
||||
buildConfigField("String", "BASE_URL", '"http://192.168.1.100:8000/api/"')
|
||||
buildConfigField("String", "STORAGE_URL", '"http://192.168.1.100:8000/storage/"')
|
||||
```
|
||||
|
||||
### Archivo de Configuracion
|
||||
|
||||
Ubicacion: `app/build.gradle`
|
||||
|
||||
```gradle
|
||||
android {
|
||||
defaultConfig {
|
||||
applicationId "com.iesoluciones.siodrenax"
|
||||
minSdkVersion 28
|
||||
targetSdkVersion 33
|
||||
versionCode 3
|
||||
versionName "1.00"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
buildConfigField("String", "BASE_URL", '"https://sio-api.consultoria-as.com/api/"')
|
||||
buildConfigField("String", "STORAGE_URL", '"https://sio-api.consultoria-as.com/storage/"')
|
||||
}
|
||||
release {
|
||||
minifyEnabled false
|
||||
buildConfigField("String", "BASE_URL", '"https://sio-api.consultoria-as.com/api/"')
|
||||
buildConfigField("String", "STORAGE_URL", '"https://sio-api.consultoria-as.com/storage/"')
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints Utilizados
|
||||
|
||||
### Autenticacion
|
||||
|
||||
| Metodo | Endpoint | Descripcion |
|
||||
|--------|----------|-------------|
|
||||
| POST | /login | Iniciar sesion |
|
||||
|
||||
### Operador
|
||||
|
||||
| Metodo | Endpoint | Descripcion |
|
||||
|--------|----------|-------------|
|
||||
| GET | /operador/checklist | Obtener checklist del vehiculo |
|
||||
| GET | /operador/checklist/vehiculos | Obtener vehiculos disponibles |
|
||||
| POST | /operador/checklist | Enviar checklist completado |
|
||||
| POST | /operador/iniciarjornada | Iniciar jornada laboral |
|
||||
| POST | /operador/finalizarjornada/{id} | Finalizar jornada |
|
||||
| GET | /operador/solicitud_servicios | Obtener servicios asignados |
|
||||
| GET | /operador/solicitud_servicios/{id} | Detalle de servicio |
|
||||
| POST | /operador/solicitud_servicios/iniciar | Iniciar servicio |
|
||||
| POST | /operador/solicitud_servicios/finalizar-new | Finalizar servicio |
|
||||
| POST | /operador/solicitud_servicios/verificar/servicios | Verificar servicios |
|
||||
| GET | /operador/servicios/diasiguiente | Servicios del dia siguiente |
|
||||
| POST | /operador/vehiculos_incidencias | Reportar incidencia vehiculo |
|
||||
| POST | /operador/vehiculos_incidencias/ultima_incidencia | Ultima incidencia |
|
||||
| PUT | /operador/vehiculos_incidencias/{id}/resolver | Resolver incidencia |
|
||||
|
||||
### Supervisor de Operaciones
|
||||
|
||||
| Metodo | Endpoint | Descripcion |
|
||||
|--------|----------|-------------|
|
||||
| GET | /supervisoroperaciones/asesores | Listar operadores |
|
||||
| GET | /supervisoroperaciones/asesores/{id}/servicios | Servicios de operador |
|
||||
| POST | /supervisoroperaciones/iniciarjornada | Iniciar jornada supervisor |
|
||||
| POST | /supervisoroperaciones/finalizarjornada/{id} | Finalizar jornada |
|
||||
|
||||
---
|
||||
|
||||
## Dependencias Principales
|
||||
|
||||
### Networking (Retrofit + OkHttp)
|
||||
|
||||
```gradle
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
|
||||
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
|
||||
```
|
||||
|
||||
### Base de Datos Local (ObjectBox)
|
||||
|
||||
```gradle
|
||||
implementation "io.objectbox:objectbox-kotlin:$objectboxVersion"
|
||||
debugImplementation "io.objectbox:objectbox-android-objectbrowser:$objectboxVersion"
|
||||
```
|
||||
|
||||
Permite almacenamiento offline de:
|
||||
- Datos de sesion
|
||||
- Servicios descargados
|
||||
- Fotos pendientes de subir
|
||||
- Respuestas de encuestas
|
||||
|
||||
### Firebase
|
||||
|
||||
```gradle
|
||||
implementation 'com.google.firebase:firebase-messaging:22.0.0'
|
||||
implementation 'com.google.firebase:firebase-crashlytics:18.2.0'
|
||||
implementation 'com.google.firebase:firebase-core:19.0.0'
|
||||
```
|
||||
|
||||
Servicios utilizados:
|
||||
- **FCM:** Notificaciones push
|
||||
- **Crashlytics:** Reportes de errores
|
||||
- **Analytics:** Estadisticas de uso
|
||||
|
||||
### UI/UX
|
||||
|
||||
```gradle
|
||||
implementation 'com.google.android.material:material:1.5.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
implementation 'com.squareup.picasso:picasso:2.71828'
|
||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||
```
|
||||
|
||||
### Mapas
|
||||
|
||||
```gradle
|
||||
implementation 'com.google.android.gms:play-services-maps:18.0.2'
|
||||
```
|
||||
|
||||
### Camara y Firma
|
||||
|
||||
```gradle
|
||||
implementation 'io.fotoapparat:fotoapparat:2.7.0' // Camara
|
||||
implementation 'com.github.gcacace:signature-pad:1.3.1' // Firma digital
|
||||
```
|
||||
|
||||
### PDF
|
||||
|
||||
```gradle
|
||||
implementation 'io.github.nvest-solutions:html-to-pdf-convertor:1.0.0'
|
||||
implementation 'com.github.naya-aastra:SkewPdfView:1.1'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Permisos Requeridos
|
||||
|
||||
| Permiso | Uso |
|
||||
|---------|-----|
|
||||
| INTERNET | Conexion al API |
|
||||
| CALL_PHONE | Llamar al cliente |
|
||||
| FOREGROUND_SERVICE | Servicios en segundo plano |
|
||||
| VIBRATE | Notificaciones |
|
||||
| WAKE_LOCK | Mantener pantalla activa |
|
||||
| READ_PHONE_STATE | Identificar dispositivo |
|
||||
| READ_EXTERNAL_STORAGE | Leer fotos |
|
||||
| WRITE_EXTERNAL_STORAGE | Guardar fotos/archivos |
|
||||
| ACCESS_FINE_LOCATION | GPS preciso |
|
||||
| ACCESS_COARSE_LOCATION | GPS aproximado |
|
||||
| ACCESS_NOTIFICATION_POLICY | Gestionar notificaciones |
|
||||
| CAMERA | Tomar fotografias |
|
||||
|
||||
---
|
||||
|
||||
## Claves y Configuracion
|
||||
|
||||
### Google Maps API Key
|
||||
|
||||
```xml
|
||||
<!-- AndroidManifest.xml -->
|
||||
<meta-data
|
||||
android:name="com.google.android.geo.API_KEY"
|
||||
android:value="YOUR_API_KEY_HERE"/>
|
||||
```
|
||||
|
||||
### Firebase
|
||||
|
||||
Archivo de configuracion: `app/google-services.json`
|
||||
|
||||
**Nota:** Este archivo contiene las credenciales de Firebase y debe mantenerse privado.
|
||||
|
||||
---
|
||||
|
||||
## Compilacion
|
||||
|
||||
### Requisitos
|
||||
|
||||
- Android Studio Arctic Fox o superior
|
||||
- JDK 8 o superior
|
||||
- Gradle 7.x
|
||||
- Android SDK 33
|
||||
|
||||
### Compilar Debug APK
|
||||
|
||||
```bash
|
||||
cd SIO-Mobile
|
||||
./gradlew assembleDebug
|
||||
```
|
||||
|
||||
APK generado en: `app/build/outputs/apk/debug/app-debug.apk`
|
||||
|
||||
### Compilar Release APK
|
||||
|
||||
```bash
|
||||
./gradlew assembleRelease
|
||||
```
|
||||
|
||||
APK generado en: `app/build/outputs/apk/release/app-release.apk`
|
||||
|
||||
**Nota:** Para release necesitas configurar signing en `build.gradle`:
|
||||
|
||||
```gradle
|
||||
android {
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile file("keystore.jks")
|
||||
storePassword "password"
|
||||
keyAlias "alias"
|
||||
keyPassword "password"
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Instalar en Dispositivo
|
||||
|
||||
```bash
|
||||
# Via ADB
|
||||
adb install app/build/outputs/apk/debug/app-debug.apk
|
||||
|
||||
# O directamente desde Android Studio
|
||||
# Run > Run 'app'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notificaciones Push (Firebase)
|
||||
|
||||
### Servicio
|
||||
|
||||
```kotlin
|
||||
// com.iesoluciones.siodrenax.services.NotificationService
|
||||
```
|
||||
|
||||
### Tipos de Notificaciones
|
||||
|
||||
| Tipo | Descripcion |
|
||||
|------|-------------|
|
||||
| Nuevo servicio | Servicio asignado al operador |
|
||||
| Cambio estatus | Actualizacion de estatus de servicio |
|
||||
| Recordatorio | Recordatorio de servicio proximo |
|
||||
| Mensaje | Mensaje del sistema/supervisor |
|
||||
|
||||
### Configuracion en Backend
|
||||
|
||||
El token FCM se registra en el login y se actualiza automaticamente.
|
||||
|
||||
---
|
||||
|
||||
## Almacenamiento Local (ObjectBox)
|
||||
|
||||
### Entidades Almacenadas
|
||||
|
||||
```kotlin
|
||||
// Sesion del usuario
|
||||
@Entity
|
||||
data class UserSession(
|
||||
@Id var id: Long = 0,
|
||||
var userId: Int,
|
||||
var token: String,
|
||||
var nombre: String,
|
||||
var email: String
|
||||
)
|
||||
|
||||
// Servicio en cache
|
||||
@Entity
|
||||
data class CachedService(
|
||||
@Id var id: Long = 0,
|
||||
var serviceId: Int,
|
||||
var jsonData: String,
|
||||
var syncStatus: Int
|
||||
)
|
||||
|
||||
// Evidencia pendiente
|
||||
@Entity
|
||||
data class PendingEvidence(
|
||||
@Id var id: Long = 0,
|
||||
var serviceId: Int,
|
||||
var photoPath: String,
|
||||
var type: String,
|
||||
var uploaded: Boolean
|
||||
)
|
||||
```
|
||||
|
||||
### Sincronizacion
|
||||
|
||||
La app sincroniza automaticamente cuando detecta conexion a internet:
|
||||
- Sube evidencias pendientes
|
||||
- Descarga servicios actualizados
|
||||
- Envia encuestas completadas
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### App no conecta al servidor
|
||||
|
||||
**Causa:** URL del API incorrecta o sin HTTPS
|
||||
|
||||
**Solucion:**
|
||||
1. Verificar `BASE_URL` en `app/build.gradle`
|
||||
2. Asegurar que sea HTTPS: `https://sio-api.consultoria-as.com/api/`
|
||||
3. Recompilar la app
|
||||
|
||||
### Error de certificado SSL
|
||||
|
||||
**Causa:** App configurada para HTTP, servidor usa HTTPS
|
||||
|
||||
**Solucion:**
|
||||
1. Actualizar URLs a HTTPS
|
||||
2. Verificar en `AndroidManifest.xml`:
|
||||
```xml
|
||||
android:usesCleartextTraffic="false"
|
||||
```
|
||||
|
||||
### Google Maps no carga
|
||||
|
||||
**Causa:** API Key invalida o sin permisos
|
||||
|
||||
**Solucion:**
|
||||
1. Verificar API Key en Google Cloud Console
|
||||
2. Habilitar Maps SDK for Android
|
||||
3. Agregar restriccion de paquete: `com.iesoluciones.siodrenax`
|
||||
|
||||
### Notificaciones no llegan
|
||||
|
||||
**Causa:** Token Firebase no registrado
|
||||
|
||||
**Solucion:**
|
||||
1. Verificar `google-services.json` actualizado
|
||||
2. Revisar permisos en Firebase Console
|
||||
3. Verificar que el token se envie al backend en login
|
||||
|
||||
### Fotos no se suben
|
||||
|
||||
**Causa:** Conexion intermitente o timeout
|
||||
|
||||
**Solucion:**
|
||||
1. Las fotos se guardan localmente (ObjectBox)
|
||||
2. Se suben automaticamente cuando hay conexion
|
||||
3. Verificar en el log si hay errores de red
|
||||
|
||||
### App crashea al iniciar
|
||||
|
||||
**Causa:** Posible corrupcion de datos locales
|
||||
|
||||
**Solucion:**
|
||||
1. Limpiar datos de la app (Settings > Apps > SIO Drenax > Clear Data)
|
||||
2. Si persiste, revisar Crashlytics para el error especifico
|
||||
|
||||
---
|
||||
|
||||
## Actualizacion de la App
|
||||
|
||||
### Cambiar Version
|
||||
|
||||
En `app/build.gradle`:
|
||||
|
||||
```gradle
|
||||
defaultConfig {
|
||||
versionCode 4 // Incrementar para cada release
|
||||
versionName "1.01" // Version visible al usuario
|
||||
}
|
||||
```
|
||||
|
||||
### Generar APK Firmado (Android Studio)
|
||||
|
||||
1. Build > Generate Signed Bundle/APK
|
||||
2. Seleccionar APK
|
||||
3. Usar keystore existente o crear nuevo
|
||||
4. Seleccionar release
|
||||
5. Generar
|
||||
|
||||
### Distribucion
|
||||
|
||||
- **Play Store:** Subir AAB (Android App Bundle)
|
||||
- **Distribucion interna:** Compartir APK directamente
|
||||
- **Firebase App Distribution:** Para pruebas beta
|
||||
|
||||
---
|
||||
|
||||
## Estructura de Respuestas API
|
||||
|
||||
### Login Exitoso
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
|
||||
"user": {
|
||||
"id": 1,
|
||||
"nombre": "Operador 1",
|
||||
"email": "operador@mail.com",
|
||||
"tipo_empleado_id": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Lista de Servicios
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": [
|
||||
{
|
||||
"id": 123,
|
||||
"cliente": "Juan Perez",
|
||||
"direccion": "Calle 123, Colonia Centro",
|
||||
"servicio": "Desazolve",
|
||||
"hora": "09:00",
|
||||
"estatus_id": 4,
|
||||
"estatus_nombre": "Pendiente"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Error
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "Token expirado",
|
||||
"code": 401
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tecnologias Utilizadas
|
||||
|
||||
- **Kotlin** - Lenguaje principal
|
||||
- **Android SDK 33** - Target API
|
||||
- **Retrofit** - Cliente HTTP
|
||||
- **ObjectBox** - Base de datos local
|
||||
- **Firebase** - Notificaciones y analytics
|
||||
- **Google Maps** - Mapas y geolocalizacion
|
||||
- **Fotoapparat** - Camara
|
||||
- **Glide/Picasso** - Carga de imagenes
|
||||
- **Material Design** - Componentes UI
|
||||
|
||||
---
|
||||
|
||||
## Contacto
|
||||
|
||||
| Campo | Valor |
|
||||
|-------|-------|
|
||||
| Sistema | SIO (Sistema Integral de Operaciones) |
|
||||
| Empresa | Drenax |
|
||||
| Package | com.iesoluciones.siodrenax |
|
||||
| Desarrollo | IE Soluciones |
|
||||
| Dominio | consultoria-as.com |
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.0
|
||||
**Ultima actualizacion:** 2026-01-17
|
||||
1
app/.gitignore
vendored
Normal file
1
app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
109
app/build.gradle
Normal file
109
app/build.gradle
Normal file
@@ -0,0 +1,109 @@
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'kotlin-kapt'
|
||||
}
|
||||
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
apply plugin: 'com.google.firebase.crashlytics'
|
||||
|
||||
android {
|
||||
compileSdkVersion 33
|
||||
defaultConfig {
|
||||
applicationId "com.iesoluciones.siodrenax"
|
||||
minSdkVersion 28
|
||||
targetSdkVersion 33
|
||||
versionCode 3
|
||||
//versionName "0.48"
|
||||
versionName "1.00"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true // To accept variables colors in vectors
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
// -------- API --------
|
||||
buildConfigField("String", "BASE_URL", '"https://sio-api.consultoria-as.com/api/"') //PROD - Cloudflare Tunnel
|
||||
buildConfigField("String", "STORAGE_URL", '"https://sio-api.consultoria-as.com/storage/"') //PROD STORAGE
|
||||
//buildConfigField("String", "BASE_URL", '"http://107.170.231.250/v1/api/"') //PROD OLD
|
||||
//buildConfigField("String", "STORAGE_URL", '"http://107.170.231.250/storage/"') //PROD STORAGE OLD
|
||||
}
|
||||
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
// -------- API --------
|
||||
buildConfigField("String", "BASE_URL", '"https://sio-api.consultoria-as.com/api/"') //PROD - Cloudflare Tunnel
|
||||
buildConfigField("String", "STORAGE_URL", '"https://sio-api.consultoria-as.com/storage/"') //PROD STORAGE
|
||||
//buildConfigField("String", "BASE_URL", '"http://107.170.231.250/v1/api/"') //PROD OLD
|
||||
//buildConfigField("String", "STORAGE_URL", '"http://107.170.231.250/storage/"') //PROD STORAGE OLD
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation 'androidx.work:work-runtime:2.8.0'
|
||||
implementation 'com.google.android.material:material:1.5.0'
|
||||
|
||||
implementation 'com.squareup.picasso:picasso:2.71828'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' // Android Jetpack
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1' //Android Jetpack
|
||||
implementation "android.arch.work:work-runtime:1.0.1" //Android Jetpack //Android Jetpack
|
||||
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' //RxAndroid
|
||||
implementation 'io.reactivex.rxjava2:rxjava:2.2.2' //RxJava
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.4.0' //GSON Converter for Retrofit
|
||||
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' //Rx Requests for Retrofit
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1' //Logging interceptor for every Request
|
||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
||||
implementation 'com.google.android.gms:play-services-maps:18.0.2'// Google Maps Android API
|
||||
|
||||
// ----- ObjectBox Data Browser -----
|
||||
debugImplementation "io.objectbox:objectbox-android-objectbrowser:$objectboxVersion"
|
||||
releaseImplementation "io.objectbox:objectbox-android:$objectboxVersion"
|
||||
implementation "io.objectbox:objectbox-kotlin:$objectboxVersion"
|
||||
|
||||
// ----- Testing -----
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test:runner:1.4.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
|
||||
// ----- Firebase -----
|
||||
implementation 'com.google.firebase:firebase-messaging:22.0.0'
|
||||
implementation 'com.google.firebase:firebase-crashlytics:18.2.0'
|
||||
implementation 'com.google.firebase:firebase-core:19.0.0'
|
||||
implementation platform('com.google.firebase:firebase-bom:28.3.1')
|
||||
implementation 'com.google.firebase:firebase-crashlytics-ktx'
|
||||
implementation 'com.google.firebase:firebase-analytics-ktx'
|
||||
|
||||
// ----- Camera & Sign -----
|
||||
implementation 'io.fotoapparat:fotoapparat:2.7.0'
|
||||
implementation 'com.github.gcacace:signature-pad:1.3.1'
|
||||
|
||||
// ----- HTML TO PDF -----
|
||||
implementation 'io.github.nvest-solutions:html-to-pdf-convertor:1.0.0'
|
||||
implementation 'com.github.naya-aastra:SkewPdfView:1.1'
|
||||
implementation project(':mylibrary')
|
||||
}
|
||||
|
||||
apply plugin: 'io.objectbox' // Apply last.
|
||||
48
app/google-services.json
Normal file
48
app/google-services.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "108152813393",
|
||||
"firebase_url": "https://drenaxx-f561e.firebaseio.com",
|
||||
"project_id": "drenaxx-f561e",
|
||||
"storage_bucket": "drenaxx-f561e.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:108152813393:android:6a2ce608fab88e98",
|
||||
"android_client_info": {
|
||||
"package_name": "com.iesoluciones.siodrenax"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "108152813393-sui8jok0le3f873uoceguvrss61r8e8s.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "com.iesoluciones.siodrenax",
|
||||
"certificate_hash": "43d5f941fa659b3f3e874fce11ff528d5ce26f1e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "108152813393-g09ea87ufqm21om9qt2v45fgl079d704.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyB05HH7lJlT0AIlILWlit467ArJ11W5vTc"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "108152813393-g09ea87ufqm21om9qt2v45fgl079d704.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
1153
app/objectbox-models/default.json
Normal file
1153
app/objectbox-models/default.json
Normal file
File diff suppressed because it is too large
Load Diff
1148
app/objectbox-models/default.json.bak
Normal file
1148
app/objectbox-models/default.json.bak
Normal file
File diff suppressed because it is too large
Load Diff
21
app/proguard-rules.pro
vendored
Normal file
21
app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.iesoluciones.siodrenax
|
||||
|
||||
import androidx.test.InstrumentationRegistry
|
||||
import androidx.test.runner.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getTargetContext()
|
||||
assertEquals("com.iesoluciones.siodrenax", appContext.packageName)
|
||||
}
|
||||
}
|
||||
95
app/src/main/AndroidManifest.xml
Normal file
95
app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.iesoluciones.siodrenax">
|
||||
|
||||
<uses-permission android:name="android.permission.CALL_PHONE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
|
||||
<uses-feature
|
||||
android:glEsVersion="0x00020000"
|
||||
android:required="true" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.telephony"
|
||||
android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="true">
|
||||
<activity
|
||||
android:name=".activities.PdfViewerActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:exported="true" />
|
||||
<activity android:name=".activities.OrdersManagerActivity" />
|
||||
<activity
|
||||
android:name=".activities.CameraActivity"
|
||||
android:screenOrientation="landscape" />
|
||||
<activity android:name=".activities.NextServiceActivity" />
|
||||
<activity android:name=".activities.ConfirmationActivity" />
|
||||
<activity
|
||||
android:name=".activities.SignatureActivity"
|
||||
android:screenOrientation="sensorLandscape" />
|
||||
<activity
|
||||
android:name=".activities.SurveyActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity android:name=".activities.OrderProgressActivity" />
|
||||
<activity
|
||||
android:name=".activities.OrderDetailActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity android:name=".activities.OperatorsActivity" />
|
||||
<activity android:name=".activities.WorkdayManagerActivity" />
|
||||
<activity
|
||||
android:name=".activities.OrdersActivity"
|
||||
android:launchMode="singleTask" />
|
||||
<activity android:name=".activities.WorkdayActivity" />
|
||||
<activity android:name=".activities.HerramientaSurveyActivity" />
|
||||
<activity android:name=".activities.MaterialSurveyActivity" />
|
||||
<activity android:name=".activities.RevisionSurveyActivity" />
|
||||
<activity
|
||||
android:name=".activities.LoginActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/NoPreview"
|
||||
android:windowSoftInputMode="adjustPan" />
|
||||
<activity
|
||||
android:name=".activities.SplashActivity"
|
||||
android:exported="true"
|
||||
android:screenOrientation="portrait">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.geo.API_KEY"
|
||||
android:value="AIzaSyB4TQiB2JsblDI2hvrWk__2psT3OzIPErc" /> <!-- Services -->
|
||||
<service
|
||||
android:name=".services.NotificationService"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
BIN
app/src/main/assets/images/logo_drenax.png
Normal file
BIN
app/src/main/assets/images/logo_drenax.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
BIN
app/src/main/ic_launcher-playstore.png
Normal file
BIN
app/src/main/ic_launcher-playstore.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
116
app/src/main/java/com/iesoluciones/siodrenax/App.kt
Normal file
116
app/src/main/java/com/iesoluciones/siodrenax/App.kt
Normal file
@@ -0,0 +1,116 @@
|
||||
package com.iesoluciones.siodrenax
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.iesoluciones.siodrenax.BuildConfig.BASE_URL
|
||||
import com.iesoluciones.siodrenax.entities.*
|
||||
import com.iesoluciones.siodrenax.network.Api
|
||||
import com.iesoluciones.siodrenax.network.TokenInterceptor
|
||||
import io.objectbox.Box
|
||||
import io.objectbox.BoxStore
|
||||
import io.objectbox.android.AndroidObjectBrowser
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
val preferencesHelper: PreferencesHelper by lazy { App.prefs!! }
|
||||
val api: Api by lazy { App.api!! }
|
||||
val userBox: Box<User> by lazy { App.userBox!! }
|
||||
val checkListQuestionBox: Box<CheckListQuestion> by lazy { App.checkListQuestionBox!! }
|
||||
val vehicleBox: Box<Vehicle> by lazy { App.vehicleBox!! }
|
||||
val orderBox: Box<Order> by lazy { App.orderBox!! }
|
||||
val orderProgressBox: Box<OrderProgress> by lazy { App.orderProgressBox!! }
|
||||
val evidenceBox: Box<Evidence> by lazy { App.evidenceBox!! }
|
||||
val businessQuestionBox: Box<BusinessQuestion> by lazy { App.businessQuestionBox!! }
|
||||
val domesticQuestionBox: Box<DomesticQuestion> by lazy { App.domesticQuestionBox!! }
|
||||
val negativeServiceReasonBox: Box<NegativeServiceReason> by lazy { App.negativeServiceReasonBox!! }
|
||||
val businessAnswerBox: Box<BusinessAnswer> by lazy { App.businessAnswerBox!! }
|
||||
val domesticAnswerBox: Box<DomesticAnswer> by lazy { App.domesticAnswerBox!! }
|
||||
val savedAnswerBox: Box<SavedAnswer> by lazy { App.savedAnswerBox!! }
|
||||
val operatorBox: Box<Operator> by lazy {App.operatorBox!!}
|
||||
val nextDayOrderBox: Box<NextDayOrder> by lazy {App.nextDayOrderBox!!}
|
||||
|
||||
class App : Application() {
|
||||
|
||||
companion object {
|
||||
var prefs: PreferencesHelper? = null
|
||||
var api: Api? = null
|
||||
var context: Context? = null
|
||||
var shareInstance: App? = null
|
||||
var boxStore: BoxStore? = null
|
||||
var userBox: Box<User>? = null
|
||||
var checkListQuestionBox: Box<CheckListQuestion>? = null
|
||||
var vehicleBox: Box<Vehicle>? = null
|
||||
var orderBox: Box<Order>? = null
|
||||
var orderProgressBox: Box<OrderProgress>? = null
|
||||
var evidenceBox: Box<Evidence>? = null
|
||||
var businessQuestionBox: Box<BusinessQuestion>? = null
|
||||
var domesticQuestionBox: Box<DomesticQuestion>? = null
|
||||
var negativeServiceReasonBox: Box<NegativeServiceReason>? = null
|
||||
var businessAnswerBox: Box<BusinessAnswer>? = null
|
||||
var domesticAnswerBox: Box<DomesticAnswer>? = null
|
||||
var savedAnswerBox: Box<SavedAnswer>? = null
|
||||
var operatorBox: Box<Operator>? = null
|
||||
var nextDayOrderBox: Box<NextDayOrder>? = null
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
prefs = PreferencesHelper(applicationContext)
|
||||
shareInstance = this
|
||||
context = this
|
||||
|
||||
boxStore = MyObjectBox.builder().androidContext(this).build()
|
||||
userBox = boxStore!!.boxFor(User::class.java)
|
||||
checkListQuestionBox = boxStore!!.boxFor(CheckListQuestion::class.java)
|
||||
vehicleBox = boxStore!!.boxFor(Vehicle::class.java)
|
||||
orderBox = boxStore!!.boxFor(Order::class.java)
|
||||
orderProgressBox = boxStore!!.boxFor(OrderProgress::class.java)
|
||||
evidenceBox = boxStore!!.boxFor(Evidence::class.java)
|
||||
businessQuestionBox = boxStore!!.boxFor(BusinessQuestion::class.java)
|
||||
domesticQuestionBox = boxStore!!.boxFor(DomesticQuestion::class.java)
|
||||
negativeServiceReasonBox = boxStore!!.boxFor(NegativeServiceReason::class.java)
|
||||
businessAnswerBox = boxStore!!.boxFor(BusinessAnswer::class.java)
|
||||
domesticAnswerBox = boxStore!!.boxFor(DomesticAnswer::class.java)
|
||||
savedAnswerBox = boxStore!!.boxFor(SavedAnswer::class.java)
|
||||
operatorBox = boxStore!!.boxFor(Operator::class.java)
|
||||
nextDayOrderBox = boxStore!!.boxFor(NextDayOrder::class.java)
|
||||
|
||||
//Starting ObjectBox Data Browser (ONLY FOR TEST!!!)
|
||||
// TODO Comentar antes de liberar
|
||||
if (BuildConfig.DEBUG) {
|
||||
val started = AndroidObjectBrowser(boxStore).start(this)
|
||||
Log.i("ObjectBrowser", "Started: $started")
|
||||
}
|
||||
|
||||
//Instantiate Logging interceptor
|
||||
val logging = HttpLoggingInterceptor()
|
||||
logging.level = HttpLoggingInterceptor.Level.BASIC
|
||||
|
||||
//Build HTTP Client
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(TokenInterceptor())
|
||||
.addInterceptor(logging)
|
||||
.connectTimeout(60, TimeUnit.SECONDS)
|
||||
.readTimeout(60, TimeUnit.SECONDS)
|
||||
.writeTimeout(60, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
//Build Retrofit Client
|
||||
val retrofit = Retrofit.Builder()
|
||||
.client(client)
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.baseUrl(BASE_URL)
|
||||
.build()
|
||||
|
||||
api = retrofit.create(Api::class.java)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.iesoluciones.siodrenax
|
||||
|
||||
import android.content.Context
|
||||
|
||||
class PreferencesHelper(context: Context) {
|
||||
|
||||
private val fileName = "share_preferences_file"
|
||||
private val prefs = context.getSharedPreferences(fileName, Context.MODE_PRIVATE)
|
||||
|
||||
private val TOKEN_API = "tokenApi"
|
||||
private val TOKEN_FIREBASE = "tokenFirebase"
|
||||
private val IS_MANAGER = "isManager"
|
||||
private val CHECK_LIST_PROGRESS = "checkListProgress"
|
||||
private val IS_ENABLE_HERRAMIENTA_SURVEY = "isEnableHerramientaSurvey"
|
||||
private val WORKDAY_STARTED = "workday_started"
|
||||
private val WORKDAY_ID = "workday_id"
|
||||
private val GPS_INTERVAL_IN_MINUTES = "gps_interval"
|
||||
private val ORDER_PROGRESS = "order_in_progress"
|
||||
private val IS_ENABLE_TO_SYNC = "syncEnable"
|
||||
|
||||
var tokenApi: String?
|
||||
get() = prefs.getString(TOKEN_API, null)
|
||||
set(value) = prefs.edit().putString(TOKEN_API, value).apply()
|
||||
|
||||
var tokenFirebase: String?
|
||||
get() = prefs.getString(TOKEN_FIREBASE, "default_token_firebase")
|
||||
set(value) = prefs.edit().putString(TOKEN_FIREBASE, value).apply()
|
||||
|
||||
var isManager: Boolean
|
||||
get() = prefs.getBoolean(IS_MANAGER, false)
|
||||
set(value) = prefs.edit().putBoolean(IS_MANAGER, value).apply()
|
||||
|
||||
var checkListProgress: String?
|
||||
get() = prefs.getString(CHECK_LIST_PROGRESS, null)
|
||||
set(value) = prefs.edit().putString(CHECK_LIST_PROGRESS, value).apply()
|
||||
|
||||
var isEnableHerramientaSurvey: Boolean
|
||||
get() = prefs.getBoolean(IS_ENABLE_HERRAMIENTA_SURVEY, true)
|
||||
set(value) = prefs.edit().putBoolean(IS_ENABLE_HERRAMIENTA_SURVEY, value).apply()
|
||||
|
||||
var workdayStarted: Boolean
|
||||
get() = prefs.getBoolean(WORKDAY_STARTED, false)
|
||||
set(value) = prefs.edit().putBoolean(WORKDAY_STARTED, value).apply()
|
||||
|
||||
var workdayId: Int
|
||||
get() = prefs.getInt(WORKDAY_ID, 0)
|
||||
set(value) = prefs.edit().putInt(WORKDAY_ID, value).apply()
|
||||
|
||||
var gpsInterval: Int
|
||||
get() = prefs.getInt(GPS_INTERVAL_IN_MINUTES, 3)
|
||||
set(value) = prefs.edit().putInt(GPS_INTERVAL_IN_MINUTES, value).apply()
|
||||
|
||||
var orderInProgress: Long?
|
||||
get() = prefs.getLong(ORDER_PROGRESS, 0L)
|
||||
set(value){
|
||||
if (value == null)
|
||||
prefs.edit().remove(ORDER_PROGRESS).apply()
|
||||
else
|
||||
prefs.edit().putLong(ORDER_PROGRESS, value).apply()
|
||||
}
|
||||
|
||||
var isEnableToSync: Boolean
|
||||
get() = prefs.getBoolean(IS_ENABLE_TO_SYNC, true)
|
||||
set(value) = prefs.edit().putBoolean(IS_ENABLE_TO_SYNC, value).apply()
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.animation.Animator
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityCameraBinding
|
||||
import com.iesoluciones.siodrenax.entities.Evidence
|
||||
import com.iesoluciones.siodrenax.repositories.EvidenceRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.DEFAULT_LATITUDE
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.DEFAULT_LONGITUDE
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.EVIDENCE_ID
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.EVIDENCIA
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.HIDE_ALPHA
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.HIDE_DURATION
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.SHOW_ALPHA
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.SHOW_DURATION
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.SHOW_TITLE_ALPHA
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.SHOW_TITLE_DELAY
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.SHOW_TITLE_DURATION
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import com.iesoluciones.siodrenax.utils.toastLong
|
||||
import com.iesoluciones.siodrenax.viewmodels.EvidenceViewModel
|
||||
import io.fotoapparat.Fotoapparat
|
||||
import io.fotoapparat.configuration.UpdateConfiguration
|
||||
import io.fotoapparat.error.CameraErrorListener
|
||||
import io.fotoapparat.exception.camera.CameraException
|
||||
import io.fotoapparat.log.fileLogger
|
||||
import io.fotoapparat.log.logcat
|
||||
import io.fotoapparat.log.loggers
|
||||
import io.fotoapparat.parameter.ScaleType
|
||||
import io.fotoapparat.result.BitmapPhoto
|
||||
import io.fotoapparat.result.WhenDoneListener
|
||||
import io.fotoapparat.selector.back
|
||||
import io.fotoapparat.selector.off
|
||||
import io.fotoapparat.selector.torch
|
||||
|
||||
class CameraActivity : AppCompatActivity() {
|
||||
|
||||
private var resultado: Int = RESULT_OK
|
||||
private var torchOn = false
|
||||
private var show = true
|
||||
|
||||
private lateinit var binding: ActivityCameraBinding
|
||||
private lateinit var evidenceViewModel: EvidenceViewModel
|
||||
private lateinit var evidenceRepository: EvidenceRepository
|
||||
private lateinit var evidence: Evidence
|
||||
private lateinit var fotoapparat: Fotoapparat
|
||||
private var bitmapResult: Bitmap? = null
|
||||
private lateinit var animListenerHide: Animator.AnimatorListener
|
||||
private lateinit var animListenerShow: Animator.AnimatorListener
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityCameraBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
evidenceViewModel = ViewModelProvider(this)[EvidenceViewModel::class.java]
|
||||
evidenceRepository = EvidenceRepository()
|
||||
|
||||
binding.cameraView.visibility = View.VISIBLE
|
||||
evidence = evidenceRepository.getEvidenceById(intent.getLongExtra(EVIDENCE_ID, 0L))
|
||||
|
||||
showTitle(EVIDENCIA + evidence.getTypeDescription() + " " + evidence.evidenceNo)
|
||||
fotoapparat = createFotoapparat()
|
||||
|
||||
binding.capture.setOnClickListener { takePicture() }
|
||||
binding.ivTorch.setImageResource(R.drawable.torch_off)
|
||||
binding.ivTorch.setOnClickListener { toggleTorchOnImageView() }
|
||||
binding.buttonConfirm.setOnClickListener { confirm() }
|
||||
binding.buttonCancel.setOnClickListener { cancel() }
|
||||
binding.tvCerrar.setOnClickListener {
|
||||
fotoapparat.stop()
|
||||
finish()
|
||||
}
|
||||
prepareGuidelines()
|
||||
attachObservers()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
fotoapparat.start()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
fotoapparat.stop()
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
setResult(resultado)
|
||||
super.finish()
|
||||
}
|
||||
|
||||
private fun createFotoapparat(): Fotoapparat {
|
||||
return Fotoapparat.with(this)
|
||||
.into(binding.cameraView)
|
||||
.previewScaleType(ScaleType.CenterInside)
|
||||
.lensPosition(back())
|
||||
.logger(loggers(logcat(), fileLogger(this)))
|
||||
.cameraErrorCallback(object : CameraErrorListener {
|
||||
override fun onError(e: CameraException) {
|
||||
toastLong(e.toString())
|
||||
}
|
||||
})
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun toggleTorchOnImageView() {
|
||||
torchOn = !torchOn
|
||||
binding.ivTorch.setImageResource(if (torchOn) R.drawable.torch else R.drawable.torch_off)
|
||||
fotoapparat.updateConfiguration(
|
||||
UpdateConfiguration.builder()
|
||||
.flash(if (torchOn) torch() else off())
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
private fun takePicture() {
|
||||
binding.capture.isEnabled = false
|
||||
binding.frameLoading.visibility = View.VISIBLE
|
||||
|
||||
val photoResult = fotoapparat.takePicture()
|
||||
|
||||
photoResult
|
||||
.toBitmap()
|
||||
.whenDone(object : WhenDoneListener<BitmapPhoto?> {
|
||||
override fun whenDone(it: BitmapPhoto?) {
|
||||
runOnUiThread {
|
||||
if (it != null) {
|
||||
binding.frameContent.visibility = View.VISIBLE
|
||||
binding.tvDescription.text = getString(
|
||||
R.string.evidence_description,
|
||||
EVIDENCIA,
|
||||
evidence.getTypeDescription(),
|
||||
evidence.evidenceNo
|
||||
)
|
||||
|
||||
bitmapResult = HelperUtil().scaleBitmap(it.bitmap, binding.root.context.resources.displayMetrics.widthPixels)
|
||||
binding.touchImageView.setImageBitmap(bitmapResult)
|
||||
binding.frameLoading.visibility = View.GONE
|
||||
binding.capture.isEnabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun prepareGuidelines() {
|
||||
animListenerHide = object : Animator.AnimatorListener {
|
||||
override fun onAnimationStart(animator: Animator) {}
|
||||
override fun onAnimationEnd(animator: Animator) {
|
||||
binding.tvCerrar.visibility = View.GONE
|
||||
binding.relativeFullScreen.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onAnimationCancel(animator: Animator) {}
|
||||
override fun onAnimationRepeat(animator: Animator) {}
|
||||
}
|
||||
|
||||
animListenerShow = object : Animator.AnimatorListener {
|
||||
override fun onAnimationStart(animator: Animator) {
|
||||
binding.tvCerrar.visibility = View.VISIBLE
|
||||
binding.relativeFullScreen.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animator: Animator) {}
|
||||
override fun onAnimationCancel(animator: Animator) {}
|
||||
override fun onAnimationRepeat(animator: Animator) {}
|
||||
}
|
||||
|
||||
binding.touchImageView.setOnClickListener {
|
||||
show = !show
|
||||
if (show)
|
||||
show()
|
||||
else
|
||||
hide()
|
||||
}
|
||||
}
|
||||
|
||||
private fun hide() {
|
||||
binding.relativeFullScreen.animate()
|
||||
.alpha(HIDE_ALPHA)
|
||||
.setDuration(HIDE_DURATION)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.setListener(animListenerHide)
|
||||
.start()
|
||||
|
||||
binding.tvCerrar.animate()
|
||||
.alpha(HIDE_ALPHA)
|
||||
.setDuration(HIDE_DURATION)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.setListener(animListenerHide)
|
||||
.start()
|
||||
}
|
||||
|
||||
private fun show() {
|
||||
binding.relativeFullScreen.animate()
|
||||
.alpha(SHOW_ALPHA)
|
||||
.setDuration(SHOW_DURATION)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.setListener(animListenerShow)
|
||||
.start()
|
||||
|
||||
binding.tvCerrar.animate()
|
||||
.alpha(SHOW_ALPHA)
|
||||
.setDuration(SHOW_DURATION)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.setListener(animListenerShow)
|
||||
.start()
|
||||
}
|
||||
|
||||
private fun showTitle(title: String?) {
|
||||
binding.cardTitle.visibility = View.VISIBLE
|
||||
binding.tvTitle.text = title
|
||||
binding.cardTitle.alpha = SHOW_ALPHA
|
||||
binding.cardTitle.animate()
|
||||
.alpha(SHOW_TITLE_ALPHA)
|
||||
.setDuration(SHOW_TITLE_DURATION)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.setStartDelay(SHOW_TITLE_DELAY)
|
||||
.start()
|
||||
}
|
||||
|
||||
private fun confirm() {
|
||||
if (bitmapResult != null) {
|
||||
binding.buttonConfirm.visibility = View.GONE
|
||||
binding.buttonCancel.visibility = View.GONE
|
||||
binding.buttonConfirm.isEnabled = false
|
||||
evidenceViewModel.saveImage(filesDir, bitmapResult!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun cancel() {
|
||||
bitmapResult = null
|
||||
binding.touchImageView.setImageBitmap(null)
|
||||
binding.frameContent.visibility = View.GONE
|
||||
}
|
||||
|
||||
private fun attachObservers() {
|
||||
evidenceViewModel.onImageSaved.observe(this) { evidenceSignatureLocal ->
|
||||
binding.buttonConfirm.isEnabled = true
|
||||
|
||||
if (evidenceSignatureLocal.path != null && evidenceSignatureLocal.name != null) {
|
||||
evidence.path = evidenceSignatureLocal.path
|
||||
evidence.name = evidenceSignatureLocal.name
|
||||
evidence.lat = DEFAULT_LATITUDE.toString()
|
||||
evidence.lng = DEFAULT_LONGITUDE.toString()
|
||||
evidenceRepository.saveEvidence(evidence)
|
||||
} else {
|
||||
resultado = RESULT_CANCELED
|
||||
}
|
||||
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.animation.Animator
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityConfirmationBinding
|
||||
import com.iesoluciones.siodrenax.entities.Evidence
|
||||
import com.iesoluciones.siodrenax.repositories.EvidenceRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.EVIDENCE_ID
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.EVIDENCIA
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.HIDE_ALPHA
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.HIDE_DURATION
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.SHOW_ALPHA
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.SHOW_DURATION
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import com.iesoluciones.siodrenax.utils.TouchImageView
|
||||
import com.iesoluciones.siodrenax.utils.toastLong
|
||||
|
||||
class ConfirmationActivity : AppCompatActivity(), View.OnClickListener {
|
||||
|
||||
private var show = true
|
||||
private var bitmap: Bitmap? = null
|
||||
private lateinit var evidence: Evidence
|
||||
private lateinit var evidenceRepository: EvidenceRepository
|
||||
private lateinit var animListenerHide: Animator.AnimatorListener
|
||||
private lateinit var animListenerShow: Animator.AnimatorListener
|
||||
private lateinit var binding: ActivityConfirmationBinding
|
||||
|
||||
private lateinit var tvDescription: TextView
|
||||
private lateinit var tvCerrar: TextView
|
||||
private lateinit var touchImageView: TouchImageView
|
||||
private lateinit var relativeFullScreen: RelativeLayout
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
//window.setDecorFitsSystemWindows(false)
|
||||
|
||||
binding = ActivityConfirmationBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
viewBinding()
|
||||
|
||||
evidenceRepository = EvidenceRepository()
|
||||
evidence = evidenceRepository.getEvidenceById(
|
||||
intent.getLongExtra(EVIDENCE_ID, 0L)
|
||||
)
|
||||
|
||||
try {
|
||||
bitmap = HelperUtil().decodeFromFile(evidence.path!!, 0)
|
||||
touchImageView.drawingCacheQuality = View.DRAWING_CACHE_QUALITY_HIGH
|
||||
touchImageView.setImageBitmap(bitmap)
|
||||
} catch (outOfMemoryError: OutOfMemoryError) {
|
||||
toastLong(resources.getString(R.string.out_of_memory_error))
|
||||
}
|
||||
|
||||
animListenerHide = object : Animator.AnimatorListener {
|
||||
override fun onAnimationStart(animator: Animator) {}
|
||||
override fun onAnimationEnd(animator: Animator) {
|
||||
tvCerrar.visibility = View.GONE
|
||||
relativeFullScreen.visibility = View.GONE
|
||||
}
|
||||
|
||||
override fun onAnimationCancel(animator: Animator) {}
|
||||
override fun onAnimationRepeat(animator: Animator) {}
|
||||
}
|
||||
|
||||
animListenerShow = object : Animator.AnimatorListener {
|
||||
override fun onAnimationStart(animator: Animator) {
|
||||
tvCerrar.visibility = View.VISIBLE
|
||||
relativeFullScreen.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animator: Animator) {}
|
||||
override fun onAnimationCancel(animator: Animator) {}
|
||||
override fun onAnimationRepeat(animator: Animator) {}
|
||||
}
|
||||
|
||||
tvCerrar.setOnClickListener(this)
|
||||
tvCerrar.visibility = View.VISIBLE
|
||||
val description = EVIDENCIA + evidence.getTypeDescription() + " " + evidence.evidenceNo
|
||||
tvDescription.text = description
|
||||
|
||||
touchImageView.setOnClickListener {
|
||||
show = !show
|
||||
if (show) show() else hide()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
bitmap?.recycle()
|
||||
}
|
||||
|
||||
override fun onClick(v: View?) {
|
||||
if (v != null) {
|
||||
when (v.id) {
|
||||
R.id.tvCerrar -> onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
onBackPressed()
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hide() {
|
||||
relativeFullScreen.animate()
|
||||
.alpha(HIDE_ALPHA)
|
||||
.setDuration(HIDE_DURATION)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.setListener(animListenerHide)
|
||||
.start()
|
||||
|
||||
tvCerrar.animate()
|
||||
.alpha(HIDE_ALPHA)
|
||||
.setDuration(HIDE_DURATION)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.setListener(animListenerHide)
|
||||
.start()
|
||||
}
|
||||
|
||||
private fun show() {
|
||||
relativeFullScreen.animate()
|
||||
.alpha(SHOW_ALPHA)
|
||||
.setDuration(SHOW_DURATION)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.setListener(animListenerShow)
|
||||
.start()
|
||||
|
||||
tvCerrar.animate()
|
||||
.alpha(SHOW_ALPHA)
|
||||
.setDuration(SHOW_DURATION)
|
||||
.setInterpolator(DecelerateInterpolator())
|
||||
.setListener(animListenerShow)
|
||||
.start()
|
||||
}
|
||||
|
||||
private fun viewBinding(){
|
||||
tvDescription = binding.tvDescription
|
||||
tvCerrar = binding.tvCerrar
|
||||
touchImageView = binding.touchImageView
|
||||
relativeFullScreen = binding.relativeFullScreen
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.adapters.HerramientaSurveyAdapter
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityHerramientaSurveyBinding
|
||||
import com.iesoluciones.siodrenax.entities.CheckListQuestion
|
||||
import com.iesoluciones.siodrenax.preferencesHelper
|
||||
import com.iesoluciones.siodrenax.repositories.CheckListRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import com.iesoluciones.siodrenax.utils.ListPaddingDecoration
|
||||
import com.iesoluciones.siodrenax.viewmodels.CheckListViewModel
|
||||
|
||||
class HerramientaSurveyActivity : ToolbarActivity() {
|
||||
|
||||
private lateinit var checkListRepository: CheckListRepository
|
||||
private lateinit var checkListQuestion: List<CheckListQuestion>
|
||||
private lateinit var adapter: HerramientaSurveyAdapter
|
||||
private lateinit var binding: ActivityHerramientaSurveyBinding
|
||||
private lateinit var checkListViewModel: CheckListViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityHerramientaSurveyBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = getString(R.string.herramienta)
|
||||
toolbarToLoad(toolbar)
|
||||
|
||||
checkListRepository = CheckListRepository()
|
||||
checkListQuestion = checkListRepository.getSurveyCheckList(Constants.HERRAMIENTA)
|
||||
|
||||
val recyclerView = binding.recycler
|
||||
recyclerView.visibility = View.VISIBLE
|
||||
recyclerView.addItemDecoration(ListPaddingDecoration(this@HerramientaSurveyActivity))
|
||||
|
||||
adapter = HerramientaSurveyAdapter(checkListQuestion)
|
||||
recyclerView.adapter = adapter
|
||||
recyclerView.layoutManager = LinearLayoutManager(this@HerramientaSurveyActivity)
|
||||
|
||||
checkListViewModel = ViewModelProvider(this)[CheckListViewModel::class.java]
|
||||
|
||||
attachObservers()
|
||||
|
||||
binding.btnSiguiente.text = getString(R.string.hold_to_finish)
|
||||
|
||||
binding.btnSiguiente.setOnClickListener { finalizarEncuesta() }
|
||||
}
|
||||
|
||||
private fun finalizarEncuesta() {
|
||||
AlertDialog.Builder(this@HerramientaSurveyActivity)
|
||||
.setTitle(R.string.titleDialogEncuestaOperadorFinalizar)
|
||||
.setMessage(R.string.messageDialogEncuestaOperadorFinalizar)
|
||||
.setPositiveButton(R.string.accept) { _, _ -> checkListViewModel.checkList() }
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun attachObservers() {
|
||||
checkListViewModel.isLoading.observe(this) { s ->
|
||||
if (s != null) {
|
||||
binding.btnSiguiente.visibility = View.GONE
|
||||
binding.frameLoading.visibility = View.VISIBLE
|
||||
binding.tvLoading.text = s
|
||||
} else {
|
||||
binding.btnSiguiente.isEnabled = true
|
||||
binding.frameLoading.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
checkListViewModel.checkListSuccess.observe(this) { checkResponse ->
|
||||
if (checkResponse != null) {
|
||||
preferencesHelper.checkListProgress = Constants.WORKDAY
|
||||
val intent = Intent(this@HerramientaSurveyActivity, WorkdayActivity::class.java)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
checkListViewModel.checkListFailure.observe(this) { throwable ->
|
||||
binding.btnSiguiente.visibility = View.VISIBLE
|
||||
if (throwable != null) {
|
||||
disableSurvey()
|
||||
HelperUtil().parseError(this, throwable)
|
||||
checkListViewModel.checkListFailure.postValue(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun disableSurvey() {
|
||||
if (!preferencesHelper.isEnableHerramientaSurvey)
|
||||
return
|
||||
|
||||
preferencesHelper.isEnableHerramientaSurvey = false
|
||||
|
||||
val count = checkListQuestion.count()
|
||||
for (position in 0 until count) {
|
||||
adapter.notifyItemChanged(position)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.google.android.gms.tasks.Task
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityLoginBinding
|
||||
import com.iesoluciones.siodrenax.preferencesHelper
|
||||
import com.iesoluciones.siodrenax.repositories.CheckListRepository
|
||||
import com.iesoluciones.siodrenax.utils.*
|
||||
import com.iesoluciones.siodrenax.viewmodels.LoginViewModel
|
||||
import java.io.File
|
||||
|
||||
class LoginActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityLoginBinding
|
||||
private lateinit var loginViewModel: LoginViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityLoginBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
|
||||
attachObservers()
|
||||
|
||||
binding.btnLogin.setOnClickListener { login() }
|
||||
|
||||
//binding.etEmail.setText("operador@mail.com")
|
||||
//binding.etPassword.setText("secret")
|
||||
|
||||
firebaseNotifications()
|
||||
|
||||
deleteSketchFolder()
|
||||
}
|
||||
|
||||
@SuppressLint("HardwareIds")
|
||||
private fun login() {
|
||||
val email = binding.etEmail.text.toString()
|
||||
val password = binding.etPassword.text.toString()
|
||||
|
||||
if (email.isNotEmpty() && password.isNotEmpty()) {
|
||||
val deviceId = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
|
||||
loginViewModel.login(email, password, deviceId)
|
||||
} else if (email.isEmpty()) {
|
||||
toast(getString(R.string.required_email))
|
||||
} else if (password.isEmpty()) {
|
||||
toast(getString(R.string.required_password))
|
||||
}
|
||||
}
|
||||
|
||||
private fun attachObservers() {
|
||||
|
||||
loginViewModel.isLoading.observe(this) { s ->
|
||||
if (s != null) {
|
||||
binding.btnLogin.isEnabled = false
|
||||
binding.frameLoading.visibility = View.VISIBLE
|
||||
binding.tvLoading.text = s
|
||||
} else {
|
||||
binding.btnLogin.isEnabled = true
|
||||
binding.frameLoading.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
loginViewModel.loginSuccess.observe(this) { success ->
|
||||
if (success) {
|
||||
|
||||
if (preferencesHelper.isManager) {
|
||||
goToActivity<WorkdayManagerActivity> {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
finish()
|
||||
} else if (!preferencesHelper.isManager) {
|
||||
var progressActivity: Class<*> = WorkdayActivity::class.java
|
||||
|
||||
if (CheckListRepository().isCheckListDone())
|
||||
progressActivity = RevisionSurveyActivity::class.java
|
||||
|
||||
val intent = Intent(this, progressActivity)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loginViewModel.loginFailure.observe(this) { throwable ->
|
||||
if (throwable != null) {
|
||||
HelperUtil().parseError(this, throwable)
|
||||
loginViewModel.loginFailure.postValue(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun firebaseNotifications() {
|
||||
FirebaseMessaging.getInstance().token.addOnCompleteListener { task: Task<String?> ->
|
||||
if (!task.isSuccessful) {
|
||||
Log.w("FIREBASE", getString(R.string.firebase_token_registration_failed), task.exception)
|
||||
return@addOnCompleteListener
|
||||
}
|
||||
// Get new FCM registration token
|
||||
preferencesHelper.tokenFirebase = task.result!!
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteSketchFolder(){
|
||||
try {
|
||||
File("$filesDir","pdf_sketchs").deleteRecursively()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.adapters.MaterialSurveyAdapter
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityMaterialSurveyBinding
|
||||
import com.iesoluciones.siodrenax.entities.CheckListQuestion
|
||||
import com.iesoluciones.siodrenax.preferencesHelper
|
||||
import com.iesoluciones.siodrenax.repositories.CheckListRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants
|
||||
import com.iesoluciones.siodrenax.utils.ListPaddingDecoration
|
||||
|
||||
class MaterialSurveyActivity : ToolbarActivity() {
|
||||
|
||||
private lateinit var checkListRepository: CheckListRepository
|
||||
private lateinit var checkListQuestion: List<CheckListQuestion>
|
||||
lateinit var binding: ActivityMaterialSurveyBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityMaterialSurveyBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = getString(R.string.material)
|
||||
toolbarToLoad(toolbar)
|
||||
|
||||
checkListRepository = CheckListRepository()
|
||||
checkListQuestion = checkListRepository.getSurveyCheckList(Constants.MATERIAL)
|
||||
|
||||
val recyclerView = binding.recycler
|
||||
recyclerView.visibility = View.VISIBLE
|
||||
recyclerView.addItemDecoration(ListPaddingDecoration(this@MaterialSurveyActivity))
|
||||
recyclerView.adapter = MaterialSurveyAdapter(checkListQuestion)
|
||||
recyclerView.layoutManager = LinearLayoutManager(this@MaterialSurveyActivity)
|
||||
|
||||
binding.btnSiguiente.text = getString(R.string.siguiente)
|
||||
binding.btnSiguiente.setOnClickListener { onClickBtnSiguiente() }
|
||||
}
|
||||
|
||||
private fun onClickBtnSiguiente() {
|
||||
AlertDialog.Builder(this@MaterialSurveyActivity)
|
||||
.setTitle(R.string.titleDialogEncuestaOperador)
|
||||
.setMessage(R.string.messageDialogEncuestaOperador)
|
||||
.setPositiveButton(R.string.accept) { _, _ ->
|
||||
preferencesHelper.checkListProgress = Constants.HERRAMIENTA
|
||||
val intent = Intent(this@MaterialSurveyActivity, HerramientaSurveyActivity::class.java)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.adapters.NextDayOrdersAdapter
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityNextServiceBinding
|
||||
import com.iesoluciones.siodrenax.entities.NextDayOrder
|
||||
import com.iesoluciones.siodrenax.receivers.UpdateUIReceiver
|
||||
import com.iesoluciones.siodrenax.utils.ListPaddingDecoration
|
||||
import com.iesoluciones.siodrenax.viewmodels.OrdersViewModel
|
||||
|
||||
class NextServiceActivity : ToolbarActivity(), SwipeRefreshLayout.OnRefreshListener,
|
||||
UpdateUIReceiver.UiUpdateListener {
|
||||
|
||||
private lateinit var binding: ActivityNextServiceBinding
|
||||
private lateinit var ordersViewModel: OrdersViewModel
|
||||
|
||||
private lateinit var orderList: List<NextDayOrder>
|
||||
private var adapter: NextDayOrdersAdapter? = null
|
||||
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
private lateinit var swipeRefresh: SwipeRefreshLayout
|
||||
private lateinit var tvEmpty: TextView
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityNextServiceBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
viewBinding()
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = getString(R.string.next_day_services)
|
||||
toolbarToLoad(toolbar)
|
||||
|
||||
ordersViewModel = ViewModelProvider(this)[OrdersViewModel::class.java]
|
||||
|
||||
attachToObservables()
|
||||
swipeRefresh.setOnRefreshListener(this)
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
ordersViewModel.isLoading.value = getString(R.string.loading)
|
||||
ordersViewModel.refreshNextDayOrders()
|
||||
}
|
||||
|
||||
override fun updateUI() {}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
ordersViewModel.updateNextDayOrdersFromDB()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.scale_out_airbnb)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
super.onBackPressed()
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.slide_out_right_airbnb)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
finish()
|
||||
overridePendingTransition(
|
||||
R.anim.slide_in_rigth_airbnb,
|
||||
R.anim.slide_out_right_airbnb
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onPointerCaptureChanged(hasCapture: Boolean) {}
|
||||
|
||||
private fun attachToObservables() {
|
||||
ordersViewModel.refreshNextDayOrders()
|
||||
ordersViewModel.getNextDayOrders().observe(this) { nextDayOrders ->
|
||||
orderList = nextDayOrders
|
||||
if (nextDayOrders.isNotEmpty()) {
|
||||
if (adapter == null) {
|
||||
tvEmpty.visibility = View.GONE
|
||||
recyclerView.visibility = View.VISIBLE
|
||||
recyclerView.addItemDecoration(ListPaddingDecoration(this@NextServiceActivity))
|
||||
adapter = NextDayOrdersAdapter(this@NextServiceActivity, nextDayOrders)
|
||||
val linearLayoutManager = LinearLayoutManager(this@NextServiceActivity)
|
||||
recyclerView.adapter = adapter
|
||||
recyclerView.layoutManager = linearLayoutManager
|
||||
adapter!!.notifyDataSetChanged()
|
||||
ordersViewModel.refreshNextDayOrders()
|
||||
|
||||
} else {
|
||||
tvEmpty.visibility = View.GONE
|
||||
recyclerView.visibility = View.VISIBLE
|
||||
adapter!!.setOrders(nextDayOrders)
|
||||
adapter!!.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
} else {
|
||||
recyclerView.visibility = View.GONE
|
||||
tvEmpty.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
if (swipeRefresh.isRefreshing) swipeRefresh.isRefreshing = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun viewBinding(){
|
||||
recyclerView = binding.recycler
|
||||
swipeRefresh = binding.swipeRefresh
|
||||
tvEmpty = binding.tvEmpty
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.adapters.OperatorAdapter
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityOperatorsBinding
|
||||
import com.iesoluciones.siodrenax.entities.Operator
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.OPERATOR_ID
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.OPERATOR_NAME
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import com.iesoluciones.siodrenax.utils.ListPaddingDecoration
|
||||
import com.iesoluciones.siodrenax.viewmodels.ManagerViewModel
|
||||
|
||||
class OperatorsActivity : ToolbarActivity(), OnRefreshListener,
|
||||
OperatorAdapter.OnOperatorSelectedListener {
|
||||
|
||||
private lateinit var binding: ActivityOperatorsBinding
|
||||
private lateinit var managerViewModel: ManagerViewModel
|
||||
var adapter: OperatorAdapter? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityOperatorsBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
managerViewModel = ViewModelProvider(this)[ManagerViewModel::class.java]
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = getString(R.string.t_OperatorsActivity)
|
||||
toolbarToLoad(toolbar)
|
||||
|
||||
attachToObservables()
|
||||
binding.swipeRefresh.setOnRefreshListener(this)
|
||||
managerViewModel.getOperators()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.workday, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.log_out -> showLogOutConfirmation()
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun attachToObservables(){
|
||||
managerViewModel.onCallFailure.observe(this) { throwable: Throwable? ->
|
||||
if (throwable != null) {
|
||||
HelperUtil().parseError(this@OperatorsActivity, throwable)
|
||||
managerViewModel.onCallFailure.value = null
|
||||
}
|
||||
}
|
||||
|
||||
managerViewModel.isLoading.observe(this) { s: String? ->
|
||||
if (s != null) {
|
||||
binding.frameLoading.visibility = View.VISIBLE
|
||||
binding.tvLoading.text = s
|
||||
binding.recycler.isEnabled = false
|
||||
} else {
|
||||
binding.frameLoading.visibility = View.GONE
|
||||
binding.recycler.isEnabled = true
|
||||
}
|
||||
if (binding.swipeRefresh.isRefreshing) binding.swipeRefresh.isRefreshing = false
|
||||
}
|
||||
|
||||
managerViewModel.getOperatorList()!!.observe(this) { operators: List<Operator> ->
|
||||
|
||||
//Refresh adapter and recyclerView
|
||||
if (adapter == null) {
|
||||
adapter = OperatorAdapter(operators, this@OperatorsActivity)
|
||||
binding.recycler.layoutManager = LinearLayoutManager(this@OperatorsActivity)
|
||||
binding.recycler.addItemDecoration(
|
||||
ListPaddingDecoration(this@OperatorsActivity)
|
||||
)
|
||||
binding.recycler.adapter = adapter
|
||||
} else {
|
||||
adapter!!.operatorList = operators
|
||||
adapter!!.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
managerViewModel.onWorkdaySuccess.observe(this) { success: Boolean ->
|
||||
if (success) {
|
||||
startActivity(Intent(this@OperatorsActivity, LoginActivity::class.java))
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
managerViewModel.getOperators()
|
||||
}
|
||||
|
||||
private fun showLogOutConfirmation() {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.ad_t_cerrar_sesion))
|
||||
.setMessage(getString(R.string.ad_m_cerrar_sesion))
|
||||
.setPositiveButton(getString(R.string.ad_aceptar)) { _, _ -> managerViewModel.endWorkload() }
|
||||
.setNegativeButton(getString(R.string.ad_cancelar), null)
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onOperatorClicked(operator: Operator) {
|
||||
val intent = Intent(this@OperatorsActivity, OrdersManagerActivity::class.java)
|
||||
intent.putExtra(OPERATOR_ID, operator.id)
|
||||
intent.putExtra(OPERATOR_NAME,"${operator.name} ${operator.lastName} ${operator.mothersName}")
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,373 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.*
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import android.util.Log
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.AppCompatButton
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.adapters.OrdersAdapter.Companion.inFormatter
|
||||
import com.iesoluciones.siodrenax.adapters.OrdersAdapter.Companion.outFormatter
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityOrderProgressBinding
|
||||
import com.iesoluciones.siodrenax.entities.Order
|
||||
import com.iesoluciones.siodrenax.repositories.OrdersRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.DEFAULT_LATITUDE
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.DEFAULT_LONGITUDE
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ORDER_ID
|
||||
import com.iesoluciones.siodrenax.viewmodels.OrderProgressViewModel
|
||||
import java.text.ParseException
|
||||
import java.util.*
|
||||
import android.view.WindowManager
|
||||
import android.widget.Toast
|
||||
import com.iesoluciones.siodrenax.utils.*
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.BRANCH_NAME
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.SKETCH_PATH
|
||||
|
||||
class OrderProgressActivity : ToolbarActivity() {
|
||||
|
||||
private lateinit var binding: ActivityOrderProgressBinding
|
||||
|
||||
//VIEWMODELS
|
||||
private lateinit var orderProgressViewModel: OrderProgressViewModel
|
||||
private val ordersRepository: OrdersRepository = OrdersRepository()
|
||||
private var order: Order? = null
|
||||
private var street = ""
|
||||
private var extNumber = ""
|
||||
private var neighborhoodName = ""
|
||||
private var postalCode = ""
|
||||
private val googleLocate = "geo:0,0?q="
|
||||
|
||||
//BINDINGS
|
||||
private lateinit var tvClientDemonination: TextView
|
||||
private lateinit var tvOrderName: TextView
|
||||
private lateinit var tvPayMethod: TextView
|
||||
private lateinit var tvContact: TextView
|
||||
private lateinit var tvAddress: TextView
|
||||
private lateinit var tvServiceStatus: TextView
|
||||
private lateinit var tvTitle: TextView
|
||||
private lateinit var tvCost: TextView
|
||||
private lateinit var tvOrderId: TextView
|
||||
private lateinit var tvOrderScheduledTime: TextView
|
||||
private lateinit var tvContactPhone: TextView
|
||||
private lateinit var tvLoading: TextView
|
||||
private lateinit var tvComments: TextView
|
||||
private lateinit var tvVehicle: TextView
|
||||
private lateinit var startServiceButton: AppCompatButton
|
||||
private lateinit var linearContact: LinearLayout
|
||||
private lateinit var linearComments: LinearLayout
|
||||
private lateinit var getRoute: LinearLayout
|
||||
private lateinit var frameLoading: FrameLayout
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityOrderProgressBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
initializeBinding()
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = resources.getString(R.string.t_OrderProgressActivity)
|
||||
toolbarToLoad(toolbar)
|
||||
enableHomeDisplay(true)
|
||||
toolbar.setNavigationOnClickListener { onBackPressed() }
|
||||
|
||||
orderProgressViewModel = ViewModelProvider(this)[OrderProgressViewModel::class.java]
|
||||
|
||||
attachObservers()
|
||||
|
||||
order = ordersRepository.getOrderById(intent.getLongExtra(ORDER_ID, 0L))
|
||||
|
||||
if(order == null){
|
||||
toastLong(resources.getString(R.string.error_order_detail))
|
||||
return finish()
|
||||
}
|
||||
|
||||
val orderProgress = ordersRepository.getOrderProgressById(order!!.id)
|
||||
|
||||
if (orderProgress != null) {
|
||||
startServiceButton.isEnabled = false
|
||||
startServiceButton.text = resources.getString(R.string.pendiente_envio)
|
||||
}
|
||||
|
||||
try {
|
||||
val temp: Date = inFormatter.parse(order!!.dateServiceRequest)!!
|
||||
tvClientDemonination.text = order!!.clientDenomination
|
||||
tvOrderScheduledTime.text = getString(
|
||||
R.string.scheduled_time,
|
||||
outFormatter.format(temp)
|
||||
)
|
||||
} catch (e: ParseException) {
|
||||
e.printStackTrace()
|
||||
tvClientDemonination.text = order!!.clientContactName
|
||||
}
|
||||
|
||||
tvOrderName.text = order!!.serviceName
|
||||
tvVehicle.text = order!!.vehicleCodeName
|
||||
|
||||
tvServiceStatus.text =
|
||||
if (orderProgress != null) resources.getString(R.string.sincronizando) else order!!.serviceStatusName
|
||||
|
||||
if (order!!.getClientContactCellphone.trim().isNotEmpty()) {
|
||||
tvContact.text = order!!.clientContactName
|
||||
tvContactPhone.text = getString(
|
||||
R.string.contact_phone, PhoneNumberUtils.formatNumber(
|
||||
order!!.getClientContactCellphone,
|
||||
"MX"
|
||||
)
|
||||
)
|
||||
tvContactPhone.visibility = View.VISIBLE
|
||||
} else {
|
||||
tvContact.text = order!!.clientContactName
|
||||
tvContactPhone.visibility = View.GONE
|
||||
}
|
||||
|
||||
tvPayMethod.text = order!!.payMethodName
|
||||
val drawable = StatusDrawable(order!!.serviceStatusColor1, order!!.serviceStatusColor2)
|
||||
tvTitle.background = drawable
|
||||
tvOrderId.text = "${order!!.idRequest}"
|
||||
tvCost.text = getString(R.string.cost, order!!.cost.currencyFormat())
|
||||
tvAddress.text = getString(
|
||||
R.string.address,
|
||||
order!!.streetAddress,
|
||||
order!!.extNumberAddress,
|
||||
order!!.neighborhoodNameAddress,
|
||||
order!!.clientPostalCodeAddress
|
||||
)
|
||||
|
||||
if (order!!.comments != null) {
|
||||
linearComments.visibility = View.VISIBLE
|
||||
tvComments.text = order!!.comments
|
||||
} else linearComments.visibility = View.GONE
|
||||
|
||||
linearContact.setOnLongClickListener {
|
||||
if (order!!.getClientContactCellphone.trim().isNotEmpty()) {
|
||||
if (ActivityCompat.checkSelfPermission(this@OrderProgressActivity, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions((this@OrderProgressActivity as AppCompatActivity), arrayOf(Manifest.permission.CALL_PHONE), 3)
|
||||
return@setOnLongClickListener true
|
||||
}else{
|
||||
val callIntent = Intent(Intent.ACTION_CALL)
|
||||
callIntent.data = Uri.parse("tel:" + order!!.getClientContactCellphone.trim()) // change the number
|
||||
vibrate()
|
||||
startActivity(callIntent)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
getRoute.setOnClickListener {
|
||||
if (order!!.streetAddress != null) {
|
||||
street = order!!.streetAddress!!
|
||||
}
|
||||
|
||||
if (order!!.extNumberAddress != null) {
|
||||
val en: Int
|
||||
try {
|
||||
en = order!!.extNumberAddress!!.toInt()
|
||||
if (en != 0) {
|
||||
extNumber = en.toString()
|
||||
}
|
||||
} catch (e: NumberFormatException) {
|
||||
Log.e(TAG, "Error cachado en conversion: " + e.message)
|
||||
}
|
||||
}
|
||||
|
||||
if (order!!.neighborhoodNameAddress!= null) {
|
||||
neighborhoodName = order!!.neighborhoodNameAddress!!
|
||||
}
|
||||
|
||||
if (order!!.clientPostalCodeAddress != null) {
|
||||
val pc: Int
|
||||
try {
|
||||
pc = order!!.clientPostalCodeAddress!!.toInt()
|
||||
if (pc != 0) {
|
||||
postalCode = pc.toString()
|
||||
}
|
||||
} catch (e: NumberFormatException) {
|
||||
Log.e(TAG, "Error cachado en conversion: " + e.message)
|
||||
}
|
||||
}
|
||||
|
||||
if (street !== "" && extNumber !== "" && neighborhoodName !== "" && postalCode !== "") {
|
||||
val intent = Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse("$googleLocate$street+$extNumber+$neighborhoodName+$postalCode")
|
||||
)
|
||||
startActivity(intent)
|
||||
} else {
|
||||
val addressDialog =
|
||||
AlertDialog.Builder(this@OrderProgressActivity, R.style.MyAlertDialogStyle)
|
||||
.setTitle(resources.getString(R.string.ad_t_direccion_servicio))
|
||||
.setMessage(resources.getString(R.string.ad_m_direccion_servicio))
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(
|
||||
resources.getString(R.string.ir_al_mapa)
|
||||
) { _, _ ->
|
||||
val intent = Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse("$googleLocate$street+$extNumber+$neighborhoodName+$postalCode")
|
||||
)
|
||||
startActivity(intent)
|
||||
}
|
||||
.setNegativeButton(
|
||||
resources.getString(R.string.cerrar)
|
||||
) { _, _ -> }
|
||||
val ad = addressDialog.create()
|
||||
ad.show()
|
||||
val buttonPositive = ad.getButton(DialogInterface.BUTTON_POSITIVE)
|
||||
buttonPositive.setTextColor(ContextCompat.getColor(this, R.color.primary))
|
||||
}
|
||||
|
||||
}
|
||||
startServiceButton.setOnClickListener { startService() }
|
||||
|
||||
binding.showSketch.setOnClickListener {
|
||||
if(order!!.sketchPath == null)
|
||||
toast(getString(R.string.m_no_pdf_client), Toast.LENGTH_LONG)
|
||||
else
|
||||
goToActivity<PdfViewerActivity>{
|
||||
putExtra(BRANCH_NAME, order!!.branchName)
|
||||
putExtra(SKETCH_PATH, order!!.sketchPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.scale_out_airbnb)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
super.onBackPressed()
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.slide_out_right_airbnb)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
finish()
|
||||
overridePendingTransition(
|
||||
R.anim.slide_in_rigth_airbnb,
|
||||
R.anim.slide_out_right_airbnb
|
||||
)
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun initializeBinding(){
|
||||
tvClientDemonination = binding.tvClientDenomination
|
||||
tvOrderName = binding.tvOrderName
|
||||
tvPayMethod = binding.tvPayMethod
|
||||
tvContact = binding.tvContact
|
||||
tvAddress = binding.tvAddress
|
||||
tvServiceStatus = binding.tvServiceStatus
|
||||
tvTitle = binding.tvTitle
|
||||
tvCost = binding.tvCost
|
||||
tvOrderId = binding.tvOrderId
|
||||
tvOrderScheduledTime = binding.tvOrderScheduledTime
|
||||
tvContactPhone = binding.tvContactPhone
|
||||
tvLoading = binding.tvLoading
|
||||
tvComments = binding.tvComments
|
||||
tvVehicle = binding.tvVehicle
|
||||
startServiceButton = binding.startServiceButton
|
||||
linearContact = binding.linearContact
|
||||
linearComments = binding.linearComments
|
||||
getRoute = binding.getRoute
|
||||
frameLoading = binding.frameLoading
|
||||
}
|
||||
|
||||
private fun startService() {
|
||||
val alertDialogBuilder: AlertDialog.Builder = AlertDialog.Builder(this)
|
||||
.setCancelable(false)
|
||||
.setTitle(R.string.progress_start_dialog_title)
|
||||
.setMessage(R.string.progress_start_dialog_message)
|
||||
.setPositiveButton(R.string.accept) { _, _ ->
|
||||
toastLong(getString(R.string.processing_request))
|
||||
orderProgressViewModel.startOrder(
|
||||
order!!.id.toString(),
|
||||
order!!.idRequest.toString(),
|
||||
inFormatter.format(Date()),
|
||||
DEFAULT_LATITUDE.toString(),
|
||||
DEFAULT_LONGITUDE.toString()
|
||||
)
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialogInterface, _ -> dialogInterface.dismiss() }
|
||||
|
||||
val alertDialog: AlertDialog = alertDialogBuilder.create()
|
||||
|
||||
alertDialog.window!!.setFlags(
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
)
|
||||
alertDialog.window!!.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
alertDialog.show()
|
||||
alertDialog.window!!.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
|
||||
}
|
||||
|
||||
private fun attachObservers(){
|
||||
orderProgressViewModel.onSendSuccess.observe(this) { responseBody ->
|
||||
if (responseBody != null) {
|
||||
|
||||
if (order!!.SurveyRequired == 1)
|
||||
ordersRepository.createSurveyAnswerHolders(order!!)
|
||||
|
||||
val intent = Intent(this@OrderProgressActivity, OrderDetailActivity::class.java)
|
||||
intent.putExtra(ORDER_ID, order!!.id)
|
||||
intent.flags = (Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
orderProgressViewModel.onSendSuccess.value = null
|
||||
startActivity(intent)
|
||||
finish()
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.scale_out_airbnb)
|
||||
}
|
||||
}
|
||||
|
||||
orderProgressViewModel.onSendFailure.observe(this) { throwable ->
|
||||
if (throwable != null) {
|
||||
HelperUtil().parseError(this@OrderProgressActivity, throwable)
|
||||
orderProgressViewModel.onSendFailure.value = null
|
||||
}
|
||||
}
|
||||
|
||||
orderProgressViewModel.isLoading.observe(this) { s ->
|
||||
if (s != null) {
|
||||
frameLoading.visibility = View.VISIBLE
|
||||
tvLoading.text = s
|
||||
} else {
|
||||
frameLoading.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun vibrate() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
val vibratorManager = this.getSystemService(VIBRATOR_MANAGER_SERVICE) as VibratorManager
|
||||
vibratorManager.defaultVibrator.vibrate(VibrationEffect.createOneShot(150, VibrationEffect.DEFAULT_AMPLITUDE))
|
||||
}else{
|
||||
(getSystemService(VIBRATOR_SERVICE) as Vibrator).vibrate(VibrationEffect.createOneShot(150, VibrationEffect.DEFAULT_AMPLITUDE))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.*
|
||||
import com.iesoluciones.siodrenax.adapters.OrdersAdapter
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityOrdersBinding
|
||||
import com.iesoluciones.siodrenax.entities.CheckListQuestion
|
||||
import com.iesoluciones.siodrenax.entities.Vehicle
|
||||
import com.iesoluciones.siodrenax.interfaces.OnIncidentListener
|
||||
import com.iesoluciones.siodrenax.interfaces.OnMileageListener
|
||||
import com.iesoluciones.siodrenax.receivers.UpdateUIReceiver
|
||||
import com.iesoluciones.siodrenax.receivers.UpdateUIReceiver.UiUpdateListener
|
||||
import com.iesoluciones.siodrenax.utils.Constants
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.DEFAULT_LATITUDE
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.DEFAULT_LONGITUDE
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.MILEAGE
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import com.iesoluciones.siodrenax.utils.ListPaddingDecoration
|
||||
import com.iesoluciones.siodrenax.viewmodels.IncidenceViewModel
|
||||
import com.iesoluciones.siodrenax.viewmodels.OrdersViewModel
|
||||
import com.iesoluciones.siodrenax.viewmodels.WorkdayStatusViewModel
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.observers.ResourceObserver
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.io.*
|
||||
|
||||
class OrdersActivity : ToolbarActivity(), OnMileageListener, OnIncidentListener, OnRefreshListener, UiUpdateListener {
|
||||
|
||||
private lateinit var binding: ActivityOrdersBinding
|
||||
private var localMileage: String? = null
|
||||
|
||||
private lateinit var workdayStatusViewModel: WorkdayStatusViewModel
|
||||
private lateinit var incidenceViewModel: IncidenceViewModel
|
||||
private lateinit var ordersViewModel: OrdersViewModel
|
||||
|
||||
private var adapter: OrdersAdapter? = null
|
||||
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
private lateinit var swipeRefresh: SwipeRefreshLayout
|
||||
private lateinit var frameHidden: FrameLayout
|
||||
private lateinit var frameLoading: FrameLayout
|
||||
private lateinit var tvLoading: TextView
|
||||
private lateinit var tvEmpty: TextView
|
||||
|
||||
private var changeVehicleAux = false
|
||||
private var isWaitingForExitAux = false
|
||||
|
||||
private lateinit var updateUIReceiver: UpdateUIReceiver
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// Si se abre por medio de una notificación y hay una orden en progreso, entonces se cierra
|
||||
if(intent.getBooleanExtra(Constants.EXTRA_NOTIFICATION_CLICKED, false) && preferencesHelper.orderInProgress != 0L)
|
||||
return finish()
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
localMileage = savedInstanceState.getString(MILEAGE)
|
||||
}
|
||||
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.scale_out_airbnb)
|
||||
|
||||
binding = ActivityOrdersBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = getString(R.string.t_OrdersActivity)
|
||||
toolbarToLoad(toolbar)
|
||||
|
||||
workdayStatusViewModel = ViewModelProvider(this)[WorkdayStatusViewModel::class.java]
|
||||
incidenceViewModel = ViewModelProvider(this)[IncidenceViewModel::class.java]
|
||||
ordersViewModel = ViewModelProvider(this)[OrdersViewModel::class.java]
|
||||
|
||||
//Bindings
|
||||
recyclerView = binding.recycler
|
||||
swipeRefresh = binding.swipeRefresh
|
||||
frameHidden = binding.frameHidden
|
||||
frameLoading = binding.frameLoading
|
||||
tvLoading = binding.tvLoading
|
||||
tvEmpty = binding.tvEmpty
|
||||
|
||||
attachToObservables()
|
||||
|
||||
swipeRefresh.setOnRefreshListener {
|
||||
onRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onRefresh() {
|
||||
ordersViewModel.isLoading.value = getString(R.string.loading)
|
||||
ordersViewModel.refreshOrders(filesDir.absolutePath)
|
||||
}
|
||||
|
||||
override fun onMileageInput(mileage: String?) {
|
||||
if (mileage != null) {
|
||||
localMileage = mileage
|
||||
HelperUtil().incidentDialogFragment(supportFragmentManager, this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNoIncident() {
|
||||
logout()
|
||||
}
|
||||
|
||||
override fun onIncidentInput(incident: String?) {
|
||||
if (incident != null) {
|
||||
incidenceViewModel.sendVehicleIncidence(incident)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateUI() {
|
||||
ordersViewModel.updateOrdersFromDB()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
updateUIReceiver = UpdateUIReceiver()
|
||||
updateUIReceiver.updateUIReceiver(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
updateUIReceiver.registerReceiver(this)
|
||||
}
|
||||
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
updateUIReceiver.unRegisterReceiver(this)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.orders, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.log_out -> workdayStatusViewModel.validateLogOut()
|
||||
R.id.sync -> HelperUtil().startSync()
|
||||
R.id.change_vehicle -> workdayStatusViewModel.validateChangeVehicle()
|
||||
R.id.next_day_service -> {
|
||||
val nextService = Intent(this, NextServiceActivity::class.java)
|
||||
startActivity(nextService)
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun attachToObservables() {
|
||||
|
||||
workdayStatusViewModel.isLoading.observe(this) { s ->
|
||||
if (s != null) {
|
||||
// This is a hidden frame over the activity used to not permit click the screen
|
||||
// this avoids to click the Drenax services when screen is loading
|
||||
frameHidden.visibility = View.VISIBLE
|
||||
frameLoading.visibility = View.VISIBLE
|
||||
tvLoading.text = s
|
||||
} else {
|
||||
frameLoading.visibility = View.GONE
|
||||
Handler(Looper.getMainLooper()).postDelayed(
|
||||
{ frameHidden.visibility = View.GONE },
|
||||
500
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
workdayStatusViewModel.endWorkdaySuccess.observe(this) {
|
||||
workdayStatusViewModel.logout()
|
||||
}
|
||||
|
||||
workdayStatusViewModel.endWorkdayFailure.observe(this) { throwable ->
|
||||
if (throwable != null) {
|
||||
HelperUtil().parseError(this@OrdersActivity, throwable)
|
||||
workdayStatusViewModel.endWorkdayFailure.value = null
|
||||
}
|
||||
}
|
||||
|
||||
ordersViewModel.getOrders().observe(this) { orders ->
|
||||
if (orders.isNotEmpty()) {
|
||||
if (adapter == null) {
|
||||
|
||||
tvEmpty.visibility = View.GONE
|
||||
recyclerView.visibility = View.VISIBLE
|
||||
recyclerView.addItemDecoration(ListPaddingDecoration(this@OrdersActivity))
|
||||
adapter = OrdersAdapter(this@OrdersActivity, orders)
|
||||
val linearLayoutManager = LinearLayoutManager(this@OrdersActivity)
|
||||
recyclerView.adapter = adapter
|
||||
recyclerView.layoutManager = linearLayoutManager
|
||||
adapter!!.notifyDataSetChanged()
|
||||
preferencesHelper.isEnableToSync = true
|
||||
} else {
|
||||
tvEmpty.visibility = View.GONE
|
||||
recyclerView.visibility = View.VISIBLE
|
||||
adapter!!.orders = orders
|
||||
adapter!!.notifyDataSetChanged()
|
||||
preferencesHelper.isEnableToSync = true
|
||||
}
|
||||
} else {
|
||||
recyclerView.visibility = View.GONE
|
||||
tvEmpty.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
if (swipeRefresh.isRefreshing) swipeRefresh.isRefreshing = false
|
||||
}
|
||||
|
||||
ordersViewModel.orderRefreshFailure.observe(this) { throwable ->
|
||||
if (throwable != null) {
|
||||
HelperUtil().parseError(this@OrdersActivity, throwable)
|
||||
ordersViewModel.orderRefreshFailure.postValue(null)
|
||||
}
|
||||
if (swipeRefresh.isRefreshing) swipeRefresh.isRefreshing = false
|
||||
}
|
||||
|
||||
workdayStatusViewModel.logOutSuccessObservable.observe(this) { logoutSuccess ->
|
||||
if (logoutSuccess) {
|
||||
startActivity(Intent(this@OrdersActivity, LoginActivity::class.java))
|
||||
finish()
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.scale_out_airbnb)
|
||||
}
|
||||
}
|
||||
|
||||
workdayStatusViewModel.isAllowedToLogOut.observe(this) { isAllowed ->
|
||||
if (isAllowed != null) {
|
||||
if (isAllowed) {
|
||||
showLogOutDialog(this@OrdersActivity)
|
||||
} else {
|
||||
showCantLogOutDialog(this@OrdersActivity)
|
||||
}
|
||||
workdayStatusViewModel.isAllowedToLogOut.value = null
|
||||
}
|
||||
}
|
||||
|
||||
workdayStatusViewModel.isAllowedToChangeVehicle.observe(this) { isAllowed ->
|
||||
if (isAllowed != null) {
|
||||
if (isAllowed) {
|
||||
showChangeVehicleConfirmation(this@OrdersActivity)
|
||||
} else {
|
||||
showCantChangeVehicleDialog(this@OrdersActivity)
|
||||
}
|
||||
workdayStatusViewModel.isAllowedToChangeVehicle.value = null
|
||||
}
|
||||
}
|
||||
|
||||
workdayStatusViewModel.changeVehicleSuccess.observe(this) { responseBody ->
|
||||
if (responseBody != null) {
|
||||
val obCheckList: Observable<List<CheckListQuestion>> = api.getCheckList(1)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { checkListQuestions ->
|
||||
checkListQuestionBox.put(checkListQuestions)
|
||||
checkListQuestions
|
||||
}
|
||||
val obVehicle: Observable<List<Vehicle>> = api.getVehicle()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { vehicle ->
|
||||
vehicleBox.put(vehicle)
|
||||
vehicle
|
||||
}
|
||||
|
||||
Observable.concat(obCheckList, obVehicle).subscribe(object :
|
||||
ResourceObserver<Any?>() {
|
||||
override fun onNext(token: Any) {}
|
||||
override fun onError(e: Throwable) {}
|
||||
override fun onComplete() {
|
||||
val intent = Intent(
|
||||
this@OrdersActivity,
|
||||
if (checkListQuestionBox.query().build().find().isNotEmpty())
|
||||
RevisionSurveyActivity::class.java else WorkdayActivity::class.java
|
||||
)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
incidenceViewModel.incidenceSuccess.observe(this) { response ->
|
||||
if (response != null) {
|
||||
logout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun logout() {
|
||||
// These validates the kind of logout with auxiliary flags
|
||||
if (isWaitingForExitAux) {
|
||||
workdayStatusViewModel.endWorkday(
|
||||
localMileage!!,
|
||||
DEFAULT_LATITUDE.toString(),
|
||||
DEFAULT_LONGITUDE.toString()
|
||||
)
|
||||
} else if (changeVehicleAux) {
|
||||
workdayStatusViewModel.changeVehicle(
|
||||
localMileage!!,
|
||||
DEFAULT_LATITUDE.toString(),
|
||||
DEFAULT_LONGITUDE.toString()
|
||||
)
|
||||
}
|
||||
|
||||
workdayStatusViewModel.isLoading.value = getString(R.string.loading_wait_a_moment)
|
||||
}
|
||||
|
||||
private fun showLogOutDialog(context: Context?) {
|
||||
AlertDialog.Builder(context!!)
|
||||
.setTitle(R.string.logout_dialog_title)
|
||||
.setMessage(R.string.logout_dialog_message)
|
||||
.setPositiveButton(R.string.accept) { _, _ ->
|
||||
isWaitingForExitAux = true
|
||||
HelperUtil().mileageDialogFragment(supportFragmentManager, this)
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialogInterface, _ -> dialogInterface.dismiss() }
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun showCantLogOutDialog(context: Context?) {
|
||||
AlertDialog.Builder(context!!)
|
||||
.setTitle(R.string.cant_logout_dialog_title)
|
||||
.setMessage(R.string.cant_logout_dialog_message)
|
||||
.setPositiveButton(R.string.accept, null)
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun showChangeVehicleConfirmation(context: Context?) {
|
||||
AlertDialog.Builder(context!!)
|
||||
.setTitle(getString(R.string.ad_t_cambiar_vehiculo))
|
||||
.setMessage(getString(R.string.ad_m_cambiar_vehiculo))
|
||||
.setPositiveButton(getString(R.string.ad_aceptar)) { _, _ ->
|
||||
changeVehicleAux = true
|
||||
HelperUtil().mileageDialogFragment(supportFragmentManager, this@OrdersActivity)
|
||||
}
|
||||
.setNegativeButton(R.string.ad_cancelar) { dialogInterface, _ -> dialogInterface.dismiss() }
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun showCantChangeVehicleDialog(context: Context?) {
|
||||
AlertDialog.Builder(context!!)
|
||||
.setTitle(R.string.cant_logout_dialog_title)
|
||||
.setMessage(R.string.cant_change_vehicle_dialog_message)
|
||||
.setPositiveButton(R.string.accept) { dialogInterface, _ -> dialogInterface.dismiss() }
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}
|
||||
|
||||
/*private fun showAutoCloseDialog(context: Context?) {
|
||||
AlertDialog.Builder(context!!)
|
||||
.setMessage(R.string.auto_close)
|
||||
.setPositiveButton(R.string.accept) { _, _ ->
|
||||
workdayStatusViewModel.logout()
|
||||
}
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.adapters.OrdersManagerAdapter
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityOrdersManagerBinding
|
||||
import com.iesoluciones.siodrenax.entities.Order
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.OPERATOR_ID
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.OPERATOR_NAME
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import com.iesoluciones.siodrenax.utils.ListPaddingDecoration
|
||||
import com.iesoluciones.siodrenax.viewmodels.ManagerViewModel
|
||||
|
||||
class OrdersManagerActivity : ToolbarActivity(), OnRefreshListener {
|
||||
|
||||
private lateinit var binding: ActivityOrdersManagerBinding
|
||||
private lateinit var managerViewModel: ManagerViewModel
|
||||
var adapter: OrdersManagerAdapter? = null
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityOrdersManagerBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = intent.getStringExtra(OPERATOR_NAME)
|
||||
toolbarToLoad(toolbar)
|
||||
|
||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
managerViewModel = ViewModelProvider(this)[ManagerViewModel::class.java]
|
||||
binding.swipeRefresh.setOnRefreshListener(this)
|
||||
attachObservers()
|
||||
|
||||
managerViewModel.getOperatorOrders(
|
||||
intent.getLongExtra(OPERATOR_ID, 0L).toString() + ""
|
||||
)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun attachObservers(){
|
||||
managerViewModel.onOrdersRetrieveSuccess.observe(this
|
||||
) { orders: List<Order> ->
|
||||
if (orders.isNotEmpty()) {
|
||||
if (adapter == null) {
|
||||
binding.tvEmpty.visibility = View.GONE
|
||||
binding.recycler.visibility = View.VISIBLE
|
||||
binding.recycler.addItemDecoration(ListPaddingDecoration(this@OrdersManagerActivity))
|
||||
adapter = OrdersManagerAdapter(this@OrdersManagerActivity, orders)
|
||||
val linearLayoutManager = LinearLayoutManager(this@OrdersManagerActivity)
|
||||
binding.recycler.adapter = adapter
|
||||
binding.recycler.layoutManager = linearLayoutManager
|
||||
adapter!!.notifyDataSetChanged()
|
||||
} else {
|
||||
binding.tvEmpty.visibility = View.GONE
|
||||
binding.recycler.visibility = View.VISIBLE
|
||||
adapter!!.orders = orders
|
||||
adapter!!.notifyDataSetChanged()
|
||||
}
|
||||
} else {
|
||||
binding.recycler.visibility = View.GONE
|
||||
binding.tvEmpty.visibility = View.VISIBLE
|
||||
}
|
||||
if (binding.swipeRefresh.isRefreshing) binding.swipeRefresh.isRefreshing = false
|
||||
}
|
||||
|
||||
managerViewModel.onCallFailure.observe(this) { throwable: Throwable? ->
|
||||
if (throwable != null) HelperUtil().parseError(this@OrdersManagerActivity, throwable)
|
||||
if (binding.swipeRefresh.isRefreshing) binding.swipeRefresh.isRefreshing = false
|
||||
}
|
||||
|
||||
managerViewModel.isLoading.observe(this
|
||||
) { s: String? ->
|
||||
if (s != null) {
|
||||
binding.frameLoading.visibility = View.VISIBLE
|
||||
binding.tvLoading.text = s
|
||||
} else {
|
||||
binding.frameLoading.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRefresh() {
|
||||
managerViewModel.getOperatorOrders(
|
||||
intent.getLongExtra(OPERATOR_ID, 0L).toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.pdf.PdfRenderer
|
||||
import android.os.Bundle
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.adapters.PdfViewerAdapter
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityPdfViewerBinding
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.BRANCH_NAME
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.SKETCH_PATH
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
class PdfViewerActivity : ToolbarActivity() {
|
||||
|
||||
private lateinit var binding: ActivityPdfViewerBinding
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
private var adapter: PdfViewerAdapter? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ActivityPdfViewerBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.scale_out_airbnb)
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = intent.getStringExtra(BRANCH_NAME)
|
||||
toolbarToLoad(toolbar)
|
||||
enableHomeDisplay(true)
|
||||
recyclerView = binding.recycler
|
||||
|
||||
|
||||
val file = File(intent.getStringExtra(SKETCH_PATH)!!)
|
||||
|
||||
try {
|
||||
binding.tvEmpty.visibility = View.GONE;
|
||||
openPDF(file)
|
||||
} catch (ioe: IOException) {
|
||||
binding.tvEmpty.visibility = View.VISIBLE;
|
||||
ioe.printStackTrace()
|
||||
}
|
||||
|
||||
toolbar.setNavigationOnClickListener {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun openPDF(file: File?) {
|
||||
var fileDescriptor: ParcelFileDescriptor? = null
|
||||
fileDescriptor = ParcelFileDescriptor.open(
|
||||
file, ParcelFileDescriptor.MODE_READ_ONLY
|
||||
)
|
||||
|
||||
var pdfRenderer: PdfRenderer? = null
|
||||
pdfRenderer = PdfRenderer(fileDescriptor)
|
||||
val pageCount: Int = pdfRenderer.pageCount
|
||||
|
||||
val pages : MutableList<Bitmap> = ArrayList()
|
||||
|
||||
for (i in 0 until pageCount){
|
||||
val rendererPage: PdfRenderer.Page = pdfRenderer.openPage(i)
|
||||
val rendererPageWidth: Int = rendererPage.width
|
||||
val rendererPageHeight: Int = rendererPage.height
|
||||
val bitmap: Bitmap = Bitmap.createBitmap(
|
||||
rendererPageWidth,
|
||||
rendererPageHeight,
|
||||
Bitmap.Config.ARGB_8888
|
||||
)
|
||||
|
||||
val canvas = Canvas(bitmap)
|
||||
canvas.drawColor(Color.WHITE)
|
||||
canvas.drawBitmap(bitmap, 0f, 0f, null)
|
||||
|
||||
rendererPage.render(
|
||||
bitmap, null, null,
|
||||
PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY
|
||||
)
|
||||
|
||||
pages.add(bitmap)
|
||||
rendererPage.close()
|
||||
}
|
||||
|
||||
pdfRenderer.close()
|
||||
fileDescriptor.close()
|
||||
|
||||
if(adapter == null){
|
||||
recyclerView.visibility = View.VISIBLE
|
||||
adapter = PdfViewerAdapter(this@PdfViewerActivity, pages)
|
||||
val linearLayoutManager = LinearLayoutManager(this@PdfViewerActivity)
|
||||
recyclerView.adapter = adapter
|
||||
recyclerView.layoutManager = linearLayoutManager
|
||||
adapter!!.notifyDataSetChanged()
|
||||
}else{
|
||||
recyclerView.visibility = View.VISIBLE
|
||||
adapter!!.pages = pages
|
||||
adapter!!.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.adapters.RevisionSurveyAdapter
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityRevisionSurveyBinding
|
||||
import com.iesoluciones.siodrenax.interfaces.OnIncidentShowListener
|
||||
import com.iesoluciones.siodrenax.preferencesHelper
|
||||
import com.iesoluciones.siodrenax.repositories.CheckListRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import com.iesoluciones.siodrenax.utils.ListPaddingDecoration
|
||||
import com.iesoluciones.siodrenax.utils.toast
|
||||
import com.iesoluciones.siodrenax.vehicleBox
|
||||
import com.iesoluciones.siodrenax.viewmodels.IncidenceViewModel
|
||||
|
||||
class RevisionSurveyActivity : ToolbarActivity(), OnIncidentShowListener {
|
||||
|
||||
private lateinit var binding: ActivityRevisionSurveyBinding
|
||||
private lateinit var recyclerView: RecyclerView
|
||||
private lateinit var adapter: RevisionSurveyAdapter
|
||||
private lateinit var incidenceViewModel: IncidenceViewModel
|
||||
private var incidenceId: Int? = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityRevisionSurveyBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = getString(R.string.revision)
|
||||
toolbarToLoad(toolbar)
|
||||
|
||||
preferencesHelper.checkListProgress = Constants.REVISION
|
||||
binding.btnSiguiente.text = getString(R.string.siguiente)
|
||||
|
||||
incidenceViewModel = ViewModelProvider(this)[IncidenceViewModel::class.java]
|
||||
attachObservers()
|
||||
|
||||
val checkListQuestion = CheckListRepository().getSurveyCheckList(Constants.REVISION)
|
||||
|
||||
val vehicle: ArrayList<String> = ArrayList()
|
||||
val vehicleIds: ArrayList<Long> = ArrayList()
|
||||
vehicle.add(getString(R.string.seleccionaVehiculo))
|
||||
vehicleIds.add(0)
|
||||
|
||||
for (v in vehicleBox.all){
|
||||
vehicle.add(v.nombre)
|
||||
vehicleIds.add(v.id)
|
||||
}
|
||||
|
||||
recyclerView = binding.recycler
|
||||
recyclerView.visibility = View.VISIBLE
|
||||
recyclerView.addItemDecoration(ListPaddingDecoration(this@RevisionSurveyActivity))
|
||||
|
||||
adapter = RevisionSurveyAdapter(
|
||||
binding.btnSiguiente,
|
||||
checkListQuestion,
|
||||
vehicle,
|
||||
vehicleIds
|
||||
)
|
||||
|
||||
recyclerView.adapter = adapter
|
||||
recyclerView.layoutManager = LinearLayoutManager(this)
|
||||
|
||||
binding.btnSiguiente.setOnClickListener {
|
||||
recyclerView.clearFocus()
|
||||
onClickBtnSiguiente()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onClickBtnSiguiente() {
|
||||
incidenceViewModel.getVehicleIncidence(RevisionSurveyAdapter.vehicleSelectedId)
|
||||
}
|
||||
|
||||
private fun attachObservers() {
|
||||
incidenceViewModel.isLoading.observe(this) { s ->
|
||||
if (s != null) {
|
||||
binding.btnSiguiente.isEnabled = false
|
||||
binding.frameLoading.visibility = View.VISIBLE
|
||||
binding.tvLoading.text = s
|
||||
} else {
|
||||
binding.btnSiguiente.isEnabled = true
|
||||
binding.frameLoading.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
incidenceViewModel.incidenceSuccess.observe(this) { response ->
|
||||
if (response != null) {
|
||||
toast(getString(R.string.toast_incidence_solved))
|
||||
alertDialog()
|
||||
}
|
||||
}
|
||||
|
||||
incidenceViewModel.incidenceFailure.observe(this) { throwable ->
|
||||
if (throwable != null) {
|
||||
HelperUtil().parseError(this, throwable)
|
||||
incidenceViewModel.incidenceFailure.postValue(null)
|
||||
}
|
||||
}
|
||||
|
||||
incidenceViewModel.getIncidenceSuccess.observe(this) { vehicleIncidenceResponse ->
|
||||
if (vehicleIncidenceResponse != null && vehicleIncidenceResponse.id > 0) {
|
||||
incidenceId = vehicleIncidenceResponse.id
|
||||
val incidence: String = vehicleIncidenceResponse.description
|
||||
HelperUtil().incidentShowDialogFragment(supportFragmentManager, this, incidence)
|
||||
} else {
|
||||
alertDialog()
|
||||
}
|
||||
}
|
||||
|
||||
incidenceViewModel.getIncidenceFailure.observe(this) { throwable ->
|
||||
if (throwable != null) {
|
||||
HelperUtil().parseError(this, throwable)
|
||||
incidenceViewModel.getIncidenceFailure.postValue(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun alertDialog() {
|
||||
AlertDialog.Builder(this@RevisionSurveyActivity)
|
||||
.setTitle(R.string.titleDialogEncuestaOperador)
|
||||
.setMessage(R.string.messageDialogEncuestaOperador)
|
||||
.setPositiveButton(R.string.accept) { _, _ ->
|
||||
preferencesHelper.checkListProgress = Constants.MATERIAL
|
||||
val intent = Intent(this@RevisionSurveyActivity, MaterialSurveyActivity::class.java)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onIncidenceSolved() {
|
||||
incidenceViewModel.resolveVehicleIncidence(incidenceId.toString())
|
||||
}
|
||||
|
||||
override fun onIncidenceNotSolved() {
|
||||
alertDialog()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
adapter.checkListQuestionBoxObserve!!.cancel()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.AppCompatButton
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.github.gcacace.signaturepad.views.SignaturePad
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.ActivitySignatureBinding
|
||||
import com.iesoluciones.siodrenax.models.EvidenceSignatureLocal
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ANIMATE_FADE_IN_ALPHA
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ANIMATE_FADE_IN_DURATION
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ANIMATE_FADE_OUT_ALPHA
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ANIMATE_FADE_OUT_DURATION
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.EVIDENCE_ID
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.EVIDENCE_NAME
|
||||
import com.iesoluciones.siodrenax.utils.snackBar
|
||||
import com.iesoluciones.siodrenax.utils.toast
|
||||
import com.iesoluciones.siodrenax.viewmodels.EvidenceViewModel
|
||||
|
||||
class SignatureActivity : AppCompatActivity(), SignaturePad.OnSignedListener {
|
||||
|
||||
private var isAtLeastSigned = false
|
||||
|
||||
private lateinit var binding: ActivitySignatureBinding
|
||||
private lateinit var evidenceViewModel: EvidenceViewModel
|
||||
|
||||
private lateinit var coordinatorSignature: CoordinatorLayout
|
||||
private lateinit var signaturePad: SignaturePad
|
||||
private lateinit var tvTitle: TextView
|
||||
private lateinit var buttonClear: AppCompatButton
|
||||
private lateinit var buttonPrint: AppCompatButton
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.scale_out_airbnb)
|
||||
binding = ActivitySignatureBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
viewBinding()
|
||||
|
||||
signaturePad.setOnSignedListener(this)
|
||||
evidenceViewModel = ViewModelProvider(this)[EvidenceViewModel::class.java]
|
||||
attachObservers()
|
||||
|
||||
buttonClear.setOnClickListener { onClickIvClear() }
|
||||
buttonPrint.setOnClickListener { onClickFabCheck() }
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.clear()
|
||||
}
|
||||
|
||||
override fun onStartSigning() {
|
||||
animateFadeOut()
|
||||
}
|
||||
|
||||
override fun onSigned() {
|
||||
isAtLeastSigned = true
|
||||
animateFadeIn()
|
||||
}
|
||||
|
||||
override fun onClear() {}
|
||||
|
||||
override fun onBackPressed() {}
|
||||
|
||||
private fun animateFadeOut() {
|
||||
tvTitle.animate().alpha(ANIMATE_FADE_OUT_ALPHA)
|
||||
.setDuration(ANIMATE_FADE_OUT_DURATION).start()
|
||||
buttonClear.animate().alpha(ANIMATE_FADE_OUT_ALPHA)
|
||||
.setDuration(ANIMATE_FADE_OUT_DURATION).start()
|
||||
buttonPrint.animate().alpha(ANIMATE_FADE_OUT_ALPHA)
|
||||
.setDuration(ANIMATE_FADE_OUT_DURATION).start()
|
||||
}
|
||||
|
||||
private fun animateFadeIn() {
|
||||
tvTitle.animate().alpha(ANIMATE_FADE_IN_ALPHA)
|
||||
.setDuration(ANIMATE_FADE_IN_DURATION).start()
|
||||
buttonPrint.animate().alpha(ANIMATE_FADE_IN_ALPHA)
|
||||
.setDuration(ANIMATE_FADE_IN_DURATION).start()
|
||||
buttonClear.animate().alpha(ANIMATE_FADE_IN_ALPHA)
|
||||
.setDuration(ANIMATE_FADE_IN_DURATION).start()
|
||||
}
|
||||
|
||||
private fun onClickIvClear() {
|
||||
signaturePad.clear()
|
||||
isAtLeastSigned = false
|
||||
}
|
||||
|
||||
private fun onClickFabCheck() {
|
||||
if (isAtLeastSigned)
|
||||
evidenceViewModel.saveImage(filesDir, signaturePad.signatureBitmap)
|
||||
else
|
||||
snackBar(getString(R.string.s_dibuje_firma))
|
||||
}
|
||||
|
||||
private fun attachObservers() {
|
||||
evidenceViewModel.onImageSaved.observe(this) { evidenceSignatureLocal: EvidenceSignatureLocal ->
|
||||
if (evidenceSignatureLocal.path != null && evidenceSignatureLocal.name != null) {
|
||||
val intent = Intent()
|
||||
intent.putExtra(EVIDENCE_ID, evidenceSignatureLocal.path)
|
||||
intent.putExtra(EVIDENCE_NAME, evidenceSignatureLocal.name)
|
||||
setResult(RESULT_OK, intent)
|
||||
finish()
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.scale_out_airbnb)
|
||||
} else {
|
||||
toast(getString(R.string.toast_ocurrio_problema))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun viewBinding() {
|
||||
coordinatorSignature = binding.coordinatorSignature
|
||||
signaturePad = binding.signaturePad
|
||||
tvTitle = binding.tvTitle
|
||||
buttonClear = binding.buttonClear
|
||||
buttonPrint = binding.buttonPrint
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
import android.os.Bundle
|
||||
import android.view.View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.iesoluciones.siodrenax.App
|
||||
import com.iesoluciones.siodrenax.databinding.ActivitySplashBinding
|
||||
import com.iesoluciones.siodrenax.preferencesHelper
|
||||
import com.iesoluciones.siodrenax.repositories.CheckListRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.LOGGED_IN
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.LOGGED_IN_MANAGER
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.NO_SESSION
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ORDER_ID
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ORDER_IN_PROGRESS
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.WORKDAY_STARTED
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.WORKDAY_STARTED_MANAGER
|
||||
import com.iesoluciones.siodrenax.utils.goToActivity
|
||||
import com.iesoluciones.siodrenax.viewmodels.SplashViewModel
|
||||
|
||||
class SplashActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivitySplashBinding
|
||||
private var splashViewModel: SplashViewModel? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivitySplashBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
window.decorView.systemUiVisibility = (SYSTEM_UI_FLAG_FULLSCREEN)
|
||||
|
||||
splashViewModel = ViewModelProvider(this)[SplashViewModel::class.java]
|
||||
attachObservers()
|
||||
|
||||
splashViewModel!!.getStartSplashObservable()
|
||||
}
|
||||
|
||||
private fun attachObservers() {
|
||||
splashViewModel!!.sessionStatusObservable.observe(this) { status ->
|
||||
processStatus(status!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun processStatus(status: Int) {
|
||||
when (status) {
|
||||
LOGGED_IN -> {
|
||||
|
||||
var progressActivity: Class<*> = WorkdayActivity::class.java
|
||||
if (CheckListRepository().isCheckListDone()) {
|
||||
when (App.prefs!!.checkListProgress) {
|
||||
Constants.REVISION -> progressActivity = RevisionSurveyActivity::class.java
|
||||
Constants.MATERIAL -> progressActivity = MaterialSurveyActivity::class.java
|
||||
Constants.HERRAMIENTA -> progressActivity =
|
||||
HerramientaSurveyActivity::class.java
|
||||
Constants.WORKDAY -> progressActivity = WorkdayActivity::class.java
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
val intent = Intent(this@SplashActivity, progressActivity)
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
LOGGED_IN_MANAGER -> {
|
||||
goToActivity<WorkdayManagerActivity> {
|
||||
flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
finish()
|
||||
}
|
||||
WORKDAY_STARTED -> {
|
||||
goToActivity<OrdersActivity> {
|
||||
flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
finish()
|
||||
}
|
||||
WORKDAY_STARTED_MANAGER -> {
|
||||
goToActivity<OperatorsActivity> {
|
||||
flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
finish()
|
||||
}
|
||||
NO_SESSION -> {
|
||||
goToActivity<LoginActivity> {
|
||||
flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
finish()
|
||||
}
|
||||
ORDER_IN_PROGRESS -> {
|
||||
goToActivity<OrderDetailActivity> {
|
||||
flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
|
||||
putExtra(ORDER_ID, preferencesHelper.orderInProgress)
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import android.widget.ScrollView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.AppCompatButton
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.adapters.MultipleViewHolderAdapter
|
||||
import com.iesoluciones.siodrenax.databinding.ActivitySurveyBinding
|
||||
import com.iesoluciones.siodrenax.entities.Order
|
||||
import com.iesoluciones.siodrenax.entities.OrderProgress
|
||||
import com.iesoluciones.siodrenax.models.Question
|
||||
import com.iesoluciones.siodrenax.repositories.OrdersRepository
|
||||
import com.iesoluciones.siodrenax.repositories.SurveyRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.DRIVE_READER
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.IDSERVICETYPEDOMESTIC
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ORDER_ID
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.PDF_URL
|
||||
import com.iesoluciones.siodrenax.utils.toast
|
||||
|
||||
class SurveyActivity : ToolbarActivity() {
|
||||
|
||||
private var orderId: Long = 0
|
||||
private var isDomestic = false
|
||||
private lateinit var skipItem: MenuItem
|
||||
private lateinit var acceptItem: MenuItem
|
||||
private lateinit var order: Order
|
||||
private lateinit var orderProgress: OrderProgress
|
||||
|
||||
private lateinit var binding: ActivitySurveyBinding
|
||||
private lateinit var ordersRepository: OrdersRepository
|
||||
private lateinit var surveyRepository: SurveyRepository
|
||||
|
||||
private lateinit var recycler: RecyclerView
|
||||
private lateinit var svWebView: ScrollView
|
||||
private lateinit var nsvSurvey: NestedScrollView
|
||||
private lateinit var webview: WebView
|
||||
private lateinit var btnPrivacyAdvice: AppCompatButton
|
||||
private lateinit var btnSaveSurvey: AppCompatButton
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.scale_out_airbnb)
|
||||
binding = ActivitySurveyBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = getString(R.string.t_SurveyActivity)
|
||||
toolbarToLoad(toolbar)
|
||||
|
||||
viewBinding()
|
||||
|
||||
ordersRepository = OrdersRepository()
|
||||
surveyRepository = SurveyRepository()
|
||||
|
||||
orderId = intent.getLongExtra(ORDER_ID, 0L)
|
||||
order = ordersRepository.getOrderById(orderId)!!
|
||||
orderProgress = ordersRepository.getOrderProgressById(orderId)!!
|
||||
isDomestic = order.idServiceType == IDSERVICETYPEDOMESTIC
|
||||
|
||||
val surveyQuestions: List<Question> = surveyRepository.getSurveyQuestions(isDomestic)
|
||||
|
||||
val adapter = MultipleViewHolderAdapter(surveyQuestions, order)
|
||||
|
||||
recycler.layoutManager = LinearLayoutManager(this)
|
||||
recycler.setHasFixedSize(true)
|
||||
recycler.adapter = adapter
|
||||
|
||||
btnPrivacyAdvice.setOnClickListener { onPrivacyAdviceClick() }
|
||||
btnSaveSurvey.setOnClickListener { onSurveyButtonClick() }
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
menuInflater.inflate(R.menu.survey, menu)
|
||||
skipItem = menu.findItem(R.id.skip)
|
||||
acceptItem = menu.findItem(R.id.accept)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.skip -> AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.ad_t_omitir_encuesta))
|
||||
.setMessage(getString(R.string.ad_m_omitir_encuesta))
|
||||
.setPositiveButton(R.string.accept) { _, _ ->
|
||||
orderProgress.isOnSurvey = false
|
||||
ordersRepository.saveOrderProgress(orderProgress)
|
||||
surveyRepository.deleteAllSavedAnswers(order)
|
||||
setResult(RESULT_OK)
|
||||
finish()
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.scale_out_airbnb)
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
R.id.accept -> {
|
||||
svWebView.visibility = View.GONE
|
||||
nsvSurvey.visibility = View.VISIBLE
|
||||
acceptItem.isVisible = false
|
||||
skipItem.isVisible = true
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {}
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
private fun onPrivacyAdviceClick() {
|
||||
skipItem.isVisible = false
|
||||
acceptItem.isVisible = true
|
||||
webview.settings.javaScriptEnabled = true
|
||||
webview.loadUrl(DRIVE_READER + PDF_URL)
|
||||
webview.webViewClient = object : WebViewClient() {
|
||||
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
|
||||
view.loadUrl(url)
|
||||
return true
|
||||
}
|
||||
}
|
||||
nsvSurvey.visibility = View.GONE
|
||||
svWebView.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun onSurveyButtonClick() {
|
||||
recycler.requestFocus()
|
||||
recycler.requestFocusFromTouch()
|
||||
btnSaveSurvey.isEnabled = false
|
||||
|
||||
if (surveyRepository.validateAnswers(order)) {
|
||||
btnSaveSurvey.isEnabled = true
|
||||
orderProgress.isOnSurvey = false
|
||||
orderProgress.shouldSendSurvey = true
|
||||
ordersRepository.saveOrderProgress(orderProgress)
|
||||
setResult(RESULT_OK)
|
||||
finish()
|
||||
overridePendingTransition(R.anim.slide_in_rigth_airbnb, R.anim.scale_out_airbnb)
|
||||
} else {
|
||||
toast(R.string.toast_faltan_campos)
|
||||
btnSaveSurvey.isEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun viewBinding() {
|
||||
recycler = binding.recycler
|
||||
svWebView = binding.svWebView
|
||||
nsvSurvey = binding.nsvSurvey
|
||||
webview = binding.webview
|
||||
btnPrivacyAdvice = binding.btnPrivacyAdvice
|
||||
btnSaveSurvey = binding.btnSaveSurvey
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityWorkdayBinding
|
||||
import com.iesoluciones.siodrenax.interfaces.OnMileageListener
|
||||
import com.iesoluciones.siodrenax.preferencesHelper
|
||||
import com.iesoluciones.siodrenax.repositories.WorkdayRepository
|
||||
import com.iesoluciones.siodrenax.utils.CircularProgressButton
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.DEFAULT_LATITUDE
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.DEFAULT_LONGITUDE
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import com.iesoluciones.siodrenax.viewmodels.WorkdayStatusViewModel
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class WorkdayActivity : ToolbarActivity(), CircularProgressButton.ProgressListener, OnMileageListener {
|
||||
|
||||
private lateinit var binding: ActivityWorkdayBinding
|
||||
private lateinit var workdayStatusViewModel: WorkdayStatusViewModel
|
||||
private lateinit var tokenFirebase: String
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityWorkdayBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = getString(R.string.t_WorkdayActivity)
|
||||
toolbarToLoad(toolbar)
|
||||
|
||||
val user = WorkdayRepository().getUser()
|
||||
binding.tvUsername.text = getString(R.string.username, user.username, user.lastName, user.mothersName)
|
||||
binding.tvInitials.text = user.username.substring(0, 1)
|
||||
binding.tvPhone.text = PhoneNumberUtils.formatNumber(user.phone, "MX")
|
||||
val inFormatter = SimpleDateFormat("dd 'de' MMM 'de' yyyy", Locale.getDefault())
|
||||
binding.tvDate.text = inFormatter.format(Date())
|
||||
|
||||
binding.iniciarJornadaButton.progressListener = this
|
||||
workdayStatusViewModel = ViewModelProvider(this)[WorkdayStatusViewModel::class.java]
|
||||
attachToObservables()
|
||||
tokenFirebase = preferencesHelper.tokenFirebase!!
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.workday, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.log_out -> workdayStatusViewModel.logout()
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onProgressStart() {}
|
||||
|
||||
override fun onProgressFinish() {
|
||||
HelperUtil().mileageDialogFragment(supportFragmentManager, this)
|
||||
}
|
||||
|
||||
override fun onMileageInput(mileage: String?) {
|
||||
if (mileage != null) {
|
||||
workdayStatusViewModel.isLoading.value = getString(R.string.loading_wait_a_moment)
|
||||
workdayStatusViewModel.startWorkday(
|
||||
tokenFirebase,
|
||||
mileage,
|
||||
DEFAULT_LATITUDE.toString(),
|
||||
DEFAULT_LONGITUDE.toString(),
|
||||
filesDir.absolutePath
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun attachToObservables() {
|
||||
workdayStatusViewModel.isLoading.observe(this) { s ->
|
||||
if (s != null) {
|
||||
binding.frameLoading.visibility = View.VISIBLE
|
||||
binding.tvLoading.text = s
|
||||
binding.iniciarJornadaButton.deactivate()
|
||||
} else {
|
||||
binding.frameLoading.visibility = View.GONE
|
||||
binding.iniciarJornadaButton.activate()
|
||||
}
|
||||
}
|
||||
|
||||
workdayStatusViewModel.logOutSuccessObservable.observe(this) { logoutSuccess ->
|
||||
if (logoutSuccess != null) if (logoutSuccess) {
|
||||
startActivity(Intent(this@WorkdayActivity, LoginActivity::class.java))
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
workdayStatusViewModel.startWorkdaySuccess.observe(this) {
|
||||
startActivity(Intent(this@WorkdayActivity, OrdersActivity::class.java))
|
||||
finish()
|
||||
}
|
||||
|
||||
workdayStatusViewModel.startWorkdayFailure.observe(this) { throwable ->
|
||||
if (throwable != null) {
|
||||
HelperUtil().parseError(this, throwable)
|
||||
workdayStatusViewModel.startWorkdayFailure.value = null
|
||||
}
|
||||
}
|
||||
|
||||
workdayStatusViewModel.endWorkdaySuccess.observe(this) {
|
||||
startActivity(Intent(this@WorkdayActivity, LoginActivity::class.java))
|
||||
finish()
|
||||
}
|
||||
|
||||
workdayStatusViewModel.endWorkdayFailure.observe(this) { throwable ->
|
||||
HelperUtil().parseError(this, throwable)
|
||||
}
|
||||
}
|
||||
|
||||
/*private fun showAutoCloseDialog(context: Context?) {
|
||||
AlertDialog.Builder(context!!)
|
||||
.setMessage(R.string.auto_close)
|
||||
.setPositiveButton(R.string.accept) { _, _ ->
|
||||
workdayStatusViewModel.logout()
|
||||
}
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.iesoluciones.siodrenax.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.iesoluciones.mylibrary.activities.ToolbarActivity
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.ActivityWorkdayBinding
|
||||
import com.iesoluciones.siodrenax.preferencesHelper
|
||||
import com.iesoluciones.siodrenax.repositories.ManagerRepository
|
||||
import com.iesoluciones.siodrenax.utils.CircularProgressButton
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import com.iesoluciones.siodrenax.utils.goToActivity
|
||||
import com.iesoluciones.siodrenax.viewmodels.ManagerViewModel
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class WorkdayManagerActivity : ToolbarActivity(), CircularProgressButton.ProgressListener {
|
||||
|
||||
private lateinit var binding: ActivityWorkdayBinding
|
||||
private lateinit var managerViewModel: ManagerViewModel
|
||||
private lateinit var managerRepository: ManagerRepository
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityWorkdayBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
@Suppress("USELESS_CAST")
|
||||
val toolbar = binding.toolbar as Toolbar
|
||||
toolbar.title = getString(R.string.t_WorkdayManagerActivity)
|
||||
toolbarToLoad(toolbar)
|
||||
|
||||
managerRepository = ManagerRepository()
|
||||
binding.iniciarJornadaButton.progressListener = this
|
||||
managerViewModel = ViewModelProvider(this)[ManagerViewModel::class.java]
|
||||
|
||||
attachToObservables()
|
||||
}
|
||||
|
||||
override fun onProgressStart() {}
|
||||
|
||||
override fun onProgressFinish() {
|
||||
managerViewModel.startWorkload()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.workday, menu)
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.log_out -> {
|
||||
managerRepository.logOut()
|
||||
goToActivity<LoginActivity> {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
finish()
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun attachToObservables() {
|
||||
managerViewModel.onCallFailure.observe(this) { throwable: Throwable? ->
|
||||
if (throwable != null) {
|
||||
HelperUtil().parseError(this@WorkdayManagerActivity, throwable)
|
||||
managerViewModel.onCallFailure.value = null
|
||||
}
|
||||
}
|
||||
|
||||
managerViewModel.isLoading.observe(this) { s: String? ->
|
||||
if (s != null) {
|
||||
binding.frameLoading.visibility = View.VISIBLE
|
||||
binding.tvLoading.text = s
|
||||
binding.iniciarJornadaButton.deactivate()
|
||||
} else {
|
||||
binding.frameLoading.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
managerViewModel.onWorkdaySuccess.observe(this) { success: Boolean ->
|
||||
if (success) {
|
||||
preferencesHelper.workdayStarted = true
|
||||
goToActivity<OperatorsActivity> {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
managerViewModel.getUser()!!.observe(this) { (_, _, username, lastName, mothersName, phone) ->
|
||||
binding.tvUsername.text = getString(R.string.username, username, lastName, mothersName)
|
||||
binding.tvInitials.text = username.substring(0, 1)
|
||||
binding.tvPhone.text = PhoneNumberUtils.formatNumber(phone, "MX")
|
||||
val inFormatter = SimpleDateFormat("dd 'de' MMM 'de' yyyy", Locale.getDefault())
|
||||
binding.tvDate.text = inFormatter.format(Date())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.iesoluciones.siodrenax.adapters
|
||||
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.checkListQuestionBox
|
||||
import com.iesoluciones.siodrenax.databinding.ViewholderHerramientaBinding
|
||||
import com.iesoluciones.siodrenax.entities.CheckListQuestion
|
||||
import com.iesoluciones.siodrenax.entities.CheckListQuestion_
|
||||
import com.iesoluciones.siodrenax.preferencesHelper
|
||||
import com.iesoluciones.siodrenax.utils.Constants
|
||||
import io.objectbox.android.AndroidScheduler
|
||||
import io.objectbox.kotlin.equal
|
||||
import io.objectbox.reactive.DataSubscription
|
||||
|
||||
class HerramientaSurveyAdapter(
|
||||
private var checkListQuestionList: List<CheckListQuestion>
|
||||
) : RecyclerView.Adapter<HerramientaSurveyAdapter.MyViewHolder>() {
|
||||
|
||||
var checkListQuestionBoxObserve: DataSubscription? = null
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
|
||||
checkListQuestionBoxObserve = checkListQuestionBox.query(
|
||||
CheckListQuestion_.tipo equal Constants.HERRAMIENTA
|
||||
)
|
||||
.build()
|
||||
.subscribe()
|
||||
.on(AndroidScheduler.mainThread())
|
||||
.observer { checkListQuestion -> checkListQuestionList = checkListQuestion }
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
||||
val binding = ViewholderHerramientaBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
return MyViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: MyViewHolder, i: Int) {
|
||||
holder.bind(checkListQuestionList[i])
|
||||
}
|
||||
|
||||
override fun getItemCount() = checkListQuestionList.size
|
||||
|
||||
class MyViewHolder(var binding: ViewholderHerramientaBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(checkListQuestion: CheckListQuestion) = with(itemView) {
|
||||
itemView.tag = checkListQuestion.id
|
||||
binding.tvQuestionTitle.text = checkListQuestion.nombre
|
||||
|
||||
binding.lLCheck.visibility =
|
||||
if (checkListQuestion.tipoCheckBox == 1) View.VISIBLE else View.GONE
|
||||
binding.frameEdit.visibility =
|
||||
if (checkListQuestion.tipoText == 1) View.VISIBLE else View.GONE
|
||||
|
||||
binding.eTComentario.setText(checkListQuestion.respuestaText)
|
||||
binding.cBQuestion.isChecked = checkListQuestion.respuestaCheckBox
|
||||
|
||||
val isEnabled = preferencesHelper.isEnableHerramientaSurvey
|
||||
|
||||
binding.eTComentario.isEnabled = isEnabled
|
||||
binding.cBQuestion.isEnabled = isEnabled
|
||||
|
||||
if (!isEnabled) {
|
||||
binding.tvQuestionTitle.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
context,
|
||||
R.color.letraGrisBloqueado
|
||||
)
|
||||
)
|
||||
} else {
|
||||
listeners()
|
||||
}
|
||||
}
|
||||
|
||||
private fun listeners() {
|
||||
val id = itemView.tag.toString().toLong()
|
||||
val objCheck: CheckListQuestion = checkListQuestionBox.get(id)
|
||||
|
||||
if (objCheck.tipoText == 1) {
|
||||
binding.eTComentario.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
objCheck.respuestaText = s.toString()
|
||||
checkListQuestionBox.put(objCheck)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (objCheck.tipoCheckBox == 1) {
|
||||
binding.cBQuestion.setOnCheckedChangeListener { _, isChecked ->
|
||||
objCheck.respuestaCheckBox = isChecked
|
||||
checkListQuestionBox.put(objCheck)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.iesoluciones.siodrenax.adapters
|
||||
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.siodrenax.checkListQuestionBox
|
||||
import com.iesoluciones.siodrenax.databinding.ViewholderMaterialBinding
|
||||
import com.iesoluciones.siodrenax.entities.CheckListQuestion
|
||||
|
||||
class MaterialSurveyAdapter(
|
||||
private val checkListQuestionList: List<CheckListQuestion>
|
||||
): RecyclerView.Adapter<MaterialSurveyAdapter.MyViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
||||
val binding = ViewholderMaterialBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
return MyViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: MyViewHolder, i: Int) {
|
||||
holder.bind(checkListQuestionList[i])
|
||||
}
|
||||
|
||||
override fun getItemCount() = checkListQuestionList.size
|
||||
|
||||
class MyViewHolder(var binding: ViewholderMaterialBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(checkListQuestion: CheckListQuestion) = with(itemView) {
|
||||
itemView.tag = checkListQuestion.id
|
||||
binding.tvQuestionTitle.text = checkListQuestion.nombre
|
||||
|
||||
binding.lLCheck.visibility = if (checkListQuestion.tipoCheckBox == 1) View.VISIBLE else View.GONE
|
||||
binding.frameEdit.visibility = if (checkListQuestion.tipoText == 1) View.VISIBLE else View.GONE
|
||||
|
||||
binding.eTComentario.setText(checkListQuestion.respuestaText)
|
||||
binding.cBQuestion.isChecked = checkListQuestion.respuestaCheckBox
|
||||
|
||||
listeners()
|
||||
}
|
||||
|
||||
private fun listeners() {
|
||||
val id = itemView.tag.toString().toLong()
|
||||
val objCheck: CheckListQuestion = checkListQuestionBox.get(id)
|
||||
|
||||
binding.eTComentario.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(
|
||||
s: CharSequence,
|
||||
start: Int,
|
||||
count: Int,
|
||||
after: Int
|
||||
) {
|
||||
}
|
||||
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
if (objCheck.tipoText == 1) {
|
||||
objCheck.respuestaText = binding.eTComentario.text.toString()
|
||||
checkListQuestionBox.put(objCheck)
|
||||
}
|
||||
}
|
||||
|
||||
override fun afterTextChanged(s: Editable) {}
|
||||
})
|
||||
|
||||
binding.cBQuestion.setOnCheckedChangeListener { _, isChecked ->
|
||||
objCheck.respuestaCheckBox = isChecked
|
||||
checkListQuestionBox.put(objCheck)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
package com.iesoluciones.siodrenax.adapters
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.DatePickerDialog
|
||||
import android.text.Editable
|
||||
import android.text.InputType
|
||||
import android.text.TextWatcher
|
||||
import android.util.Patterns
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.OnFocusChangeListener
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.appcompat.widget.AppCompatCheckBox
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.siodrenax.App
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.ViewholderAnswerOpenBinding
|
||||
import com.iesoluciones.siodrenax.databinding.ViewholderCheckboxAnswerBinding
|
||||
import com.iesoluciones.siodrenax.entities.Order
|
||||
import com.iesoluciones.siodrenax.models.Answer
|
||||
import com.iesoluciones.siodrenax.models.Question
|
||||
import com.iesoluciones.siodrenax.repositories.SurveyRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ANSWER_CHECKBOX
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ANSWER_CURRENCY
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ANSWER_DATE
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ANSWER_EMAIL
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ANSWER_NUMBER
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ANSWER_TEXT
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.CERO
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.IDSERVICETYPEDOMESTIC
|
||||
import java.text.NumberFormat
|
||||
import java.util.*
|
||||
|
||||
class MultipleViewHolderAdapter(
|
||||
private var questionList: List<Question>,
|
||||
private val order: Order
|
||||
) :
|
||||
RecyclerView.Adapter<MultipleViewHolderAdapter.AnswerViewHolder>() {
|
||||
|
||||
private val isDomestic = order.idServiceType == IDSERVICETYPEDOMESTIC
|
||||
private val surveyRepository = SurveyRepository()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AnswerViewHolder {
|
||||
when (viewType) {
|
||||
ANSWER_CHECKBOX -> return CheckBoxViewHolder(
|
||||
ViewholderCheckboxAnswerBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
ANSWER_CURRENCY, ANSWER_DATE, ANSWER_EMAIL, ANSWER_NUMBER, ANSWER_TEXT -> return OpenAnswerViewHolder(
|
||||
ViewholderAnswerOpenBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
),
|
||||
viewType
|
||||
)
|
||||
}
|
||||
throw RuntimeException("Uncaught viewholder Type")
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: AnswerViewHolder, position: Int) {
|
||||
holder.bindViews(questionList[position])
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return questionList.size
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return getViewType(questionList[position])
|
||||
}
|
||||
|
||||
abstract class AnswerViewHolder(itemView: View) :
|
||||
RecyclerView.ViewHolder(itemView) {
|
||||
abstract fun bindViews(question: Question)
|
||||
abstract fun cleanOnRecycled()
|
||||
}
|
||||
|
||||
inner class CheckBoxViewHolder(var binding: ViewholderCheckboxAnswerBinding) :
|
||||
AnswerViewHolder(binding.root), View.OnClickListener {
|
||||
private var tvQuestionTitle = binding.tvQuestionTitle
|
||||
private var linearAnswer = binding.linearAnswer
|
||||
private lateinit var answers: List<Answer>
|
||||
private lateinit var answer: Answer
|
||||
private var checkBoxes: MutableList<AppCompatCheckBox> = ArrayList()
|
||||
private lateinit var question: Question
|
||||
|
||||
override fun bindViews(question: Question) {
|
||||
this.question = question
|
||||
|
||||
if (question.getShowNumber() == 0)
|
||||
tvQuestionTitle.text = question.getTitle()
|
||||
else
|
||||
tvQuestionTitle.text = App.context!!.resources.getString(
|
||||
R.string.question_title,
|
||||
(adapterPosition + 1),
|
||||
question.getTitle()
|
||||
)
|
||||
|
||||
answers = surveyRepository.getAnswers(question, isDomestic)
|
||||
for (answer in answers) {
|
||||
val checkBox = AppCompatCheckBox(itemView.context)
|
||||
checkBox.layoutParams = ViewGroup.LayoutParams(
|
||||
TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT.toFloat(),
|
||||
itemView.context.resources.displayMetrics
|
||||
)
|
||||
.toInt(),
|
||||
TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT.toFloat(),
|
||||
itemView.context.resources.displayMetrics
|
||||
)
|
||||
.toInt()
|
||||
)
|
||||
checkBox.text = answer.getTitle()
|
||||
checkBox.isChecked = false
|
||||
checkBox.tag = answer
|
||||
checkBox.setOnClickListener(this)
|
||||
|
||||
val savedAnswer = surveyRepository.getQuestionSavedAnswer(question, order)
|
||||
if (savedAnswer != null && savedAnswer != "" && savedAnswer.toLong() == answer.getId()) {
|
||||
this.answer = answer
|
||||
checkBox.isChecked = true
|
||||
}
|
||||
|
||||
linearAnswer.addView(checkBox)
|
||||
checkBoxes.add(checkBox)
|
||||
}
|
||||
}
|
||||
|
||||
override fun cleanOnRecycled() {
|
||||
linearAnswer.removeAllViews()
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
if (!(v as AppCompatCheckBox).isChecked) {
|
||||
surveyRepository.saveQuestionAnswer(question, order, null, false)
|
||||
} else {
|
||||
answer = v.getTag() as Answer
|
||||
surveyRepository.saveQuestionAnswer(
|
||||
question,
|
||||
order,
|
||||
answer.getId().toString() + "",
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
for (checkBox in checkBoxes)
|
||||
if (checkBox.tag !== answer)
|
||||
checkBox.isChecked = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inner class OpenAnswerViewHolder(
|
||||
var binding: ViewholderAnswerOpenBinding,
|
||||
private var viewType: Int
|
||||
) :
|
||||
AnswerViewHolder(binding.root), View.OnClickListener {
|
||||
private var tvQuestionTitle = binding.tvQuestionTitle
|
||||
private var frameDate = binding.frameDate
|
||||
private var tvDate = binding.tvDate
|
||||
private var editAnswer = binding.editAnswer
|
||||
private var linearQuestion = binding.linearQuestion
|
||||
private lateinit var question: Question
|
||||
|
||||
//Calendario para obtener fecha & hora
|
||||
private val c = Calendar.getInstance()
|
||||
|
||||
//Variables para obtener la fecha
|
||||
private val mes = c[Calendar.MONTH]
|
||||
private val dia = c[Calendar.DAY_OF_MONTH]
|
||||
private val anio = c[Calendar.YEAR]
|
||||
|
||||
override fun bindViews(question: Question) {
|
||||
this.question = question
|
||||
if (question.getShowNumber() == 0)
|
||||
tvQuestionTitle.text = question.getTitle()
|
||||
else
|
||||
tvQuestionTitle.text = App.context!!.resources.getString(
|
||||
R.string.question_title,
|
||||
(adapterPosition + 1),
|
||||
question.getTitle()
|
||||
)
|
||||
|
||||
when (viewType) {
|
||||
ANSWER_CURRENCY -> {
|
||||
//Currency TextWatcher, set
|
||||
editAnswer.inputType = InputType.TYPE_CLASS_NUMBER
|
||||
editAnswer.addTextChangedListener(CurrencyTextWatcher())
|
||||
editAnswer.setText("0")
|
||||
editAnswer.onFocusChangeListener =
|
||||
OnFocusChangeListener { _, hasFocus ->
|
||||
if (!hasFocus) {
|
||||
var formatted = editAnswer.text.toString()
|
||||
formatted = formatted.replace(",".toRegex(), "")
|
||||
formatted = formatted.replace("\\$".toRegex(), "")
|
||||
surveyRepository.saveQuestionAnswer(
|
||||
question,
|
||||
order,
|
||||
formatted,
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
ANSWER_DATE -> {
|
||||
//Block clicks to show date picker, and format it
|
||||
editAnswer.visibility = View.GONE
|
||||
frameDate.visibility = View.VISIBLE
|
||||
linearQuestion.setOnClickListener(this)
|
||||
}
|
||||
ANSWER_EMAIL -> {
|
||||
//Email TextWatcher
|
||||
editAnswer.inputType = InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|
||||
editAnswer.imeOptions = EditorInfo.IME_ACTION_NEXT
|
||||
editAnswer.onFocusChangeListener =
|
||||
OnFocusChangeListener { _, hasFocus ->
|
||||
if (!hasFocus) {
|
||||
if (!isValidEmail(editAnswer.text.toString())) editAnswer.error =
|
||||
"Correo inválido" else surveyRepository.saveQuestionAnswer(
|
||||
question, order, editAnswer.text.toString(), true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
ANSWER_NUMBER -> //Number formatter
|
||||
editAnswer.inputType = InputType.TYPE_CLASS_NUMBER
|
||||
ANSWER_TEXT -> {
|
||||
//Text TextWatcher
|
||||
editAnswer.imeOptions = EditorInfo.IME_ACTION_NEXT
|
||||
editAnswer.onFocusChangeListener =
|
||||
OnFocusChangeListener { _, hasFocus ->
|
||||
var answers = editAnswer.text.toString()
|
||||
answers = answers.replace(" ", "")
|
||||
if (!hasFocus && answers != "") {
|
||||
surveyRepository.saveQuestionAnswer(
|
||||
question,
|
||||
order,
|
||||
editAnswer.text.toString(),
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (!editAnswer.hasFocus() && editAnswer.text.toString() == "")
|
||||
surveyRepository.saveQuestionAnswer(question, order, null, true)
|
||||
}
|
||||
}
|
||||
|
||||
val savedAnswer = surveyRepository.getQuestionSavedAnswer(question, order)
|
||||
if (viewType == ANSWER_DATE)
|
||||
tvDate.text = savedAnswer
|
||||
else
|
||||
editAnswer.setText(savedAnswer)
|
||||
}
|
||||
|
||||
override fun cleanOnRecycled() {}
|
||||
private fun isValidEmail(target: String?): Boolean {
|
||||
return if (target == null) {
|
||||
false
|
||||
} else {
|
||||
//android Regex to check the email address Validation
|
||||
Patterns.EMAIL_ADDRESS.matcher(target).matches()
|
||||
}
|
||||
}
|
||||
|
||||
private fun obtenerFecha() {
|
||||
val recogerFecha = DatePickerDialog(
|
||||
itemView.context,
|
||||
{ _, year, month, dayOfMonth -> //Esta variable lo que realiza es aumentar en uno el mes ya que comienza desde 0 = enero
|
||||
val mesActual = month + 1
|
||||
//Formateo el día obtenido: antepone el 0 si son menores de 10
|
||||
val diaFormateado =
|
||||
if (dayOfMonth < 10) CERO + dayOfMonth.toString() else dayOfMonth.toString()
|
||||
//Formateo el mes obtenido: antepone el 0 si son menores de 10
|
||||
val mesFormateado =
|
||||
if (mesActual < 10) CERO + mesActual.toString() else mesActual.toString()
|
||||
//Muestro la fecha con el formato deseado
|
||||
val dateFormatted = App.context!!.resources.getString(
|
||||
R.string.date_format,
|
||||
year.toString(),
|
||||
mesFormateado,
|
||||
diaFormateado
|
||||
)
|
||||
|
||||
tvDate.text = dateFormatted
|
||||
surveyRepository.saveQuestionAnswer(
|
||||
question,
|
||||
order,
|
||||
dateFormatted,
|
||||
true
|
||||
)
|
||||
}, //Estos valores deben ir en ese orden, de lo contrario no mostrara la fecha actual
|
||||
anio, mes, dia
|
||||
)
|
||||
//Muestro el widget
|
||||
recogerFecha.show()
|
||||
}
|
||||
|
||||
internal inner class CurrencyTextWatcher : TextWatcher {
|
||||
private var current = ""
|
||||
|
||||
@Synchronized
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
if (s.toString() != current) {
|
||||
editAnswer.removeTextChangedListener(this)
|
||||
val cleanString = s.toString().replace("[$,.]".toRegex(), "")
|
||||
var parsed = 0.0
|
||||
try {
|
||||
parsed = cleanString.toDouble()
|
||||
} catch (ignored: NumberFormatException) {
|
||||
}
|
||||
val formatted = NumberFormat.getCurrencyInstance().format(parsed / 100)
|
||||
current = formatted
|
||||
editAnswer.setText(formatted)
|
||||
editAnswer.setSelection(formatted.length)
|
||||
editAnswer.addTextChangedListener(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
val imm =
|
||||
itemView.context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.hideSoftInputFromWindow(itemView.windowToken, 0)
|
||||
obtenerFecha()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun getViewType(question: Question): Int {
|
||||
return when (surveyRepository.getAnswers(question, isDomestic)[0].getType()) {
|
||||
"Checkbox" -> ANSWER_CHECKBOX
|
||||
"Fecha" -> ANSWER_DATE
|
||||
"Email" -> ANSWER_EMAIL
|
||||
"Numero" -> ANSWER_NUMBER
|
||||
"Moneda" -> ANSWER_CURRENCY
|
||||
"Texto" -> ANSWER_TEXT
|
||||
else -> throw RuntimeException("Question Type Not Supported")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.iesoluciones.siodrenax.adapters
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Context.VIBRATOR_SERVICE
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
import android.os.VibratorManager
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.ViewholderOrderBinding
|
||||
import com.iesoluciones.siodrenax.entities.NextDayOrder
|
||||
import com.iesoluciones.siodrenax.utils.StatusDrawable
|
||||
import com.iesoluciones.siodrenax.utils.currencyFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class NextDayOrdersAdapter(
|
||||
private val context: Context,
|
||||
private var orders: List<NextDayOrder>
|
||||
) : RecyclerView.Adapter<NextDayOrdersAdapter.ViewHolder>() {
|
||||
|
||||
companion object {
|
||||
val inFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||
val outFormatter = SimpleDateFormat("HH:mm", Locale.getDefault())
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val binding =
|
||||
ViewholderOrderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(binding, context)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(orders[position])
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return orders.size
|
||||
}
|
||||
|
||||
fun setOrders(orders: List<NextDayOrder>) {
|
||||
this.orders = orders
|
||||
}
|
||||
|
||||
class ViewHolder(
|
||||
val binding: ViewholderOrderBinding,
|
||||
val context: Context
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
private val tvClientDenomination = binding.tvClientDenomination
|
||||
private val tvOrderName = binding.tvOrderName
|
||||
private val tvPayMethod = binding.tvPayMethod
|
||||
private val tvContact = binding.tvContact
|
||||
private val tvAddress = binding.tvAddress
|
||||
private val tvServiceStatus = binding.tvServiceStatus
|
||||
private val tvTitle = binding.tvTitle
|
||||
private val tvCost = binding.tvCost
|
||||
private val tvOrderId = binding.tvOrderId
|
||||
private val tvOrderScheduledTime = binding.tvOrderScheduledTime
|
||||
private val tvContactPhone = binding.tvContactPhone
|
||||
private val linearContact = binding.linearContact
|
||||
private val linearComments = binding.linearComments
|
||||
private val tvComments = binding.tvComments
|
||||
private val tvVehicle = binding.tvVehicle
|
||||
|
||||
fun bind(order: NextDayOrder) = with(itemView) {
|
||||
try {
|
||||
val temp: Date = inFormatter.parse(order.dateServiceRequest)!!
|
||||
inFormatter.parse(order.dateServiceRequest)!!
|
||||
tvClientDenomination.text = order.clientDenomination
|
||||
tvOrderScheduledTime.text = context.resources.getString(
|
||||
R.string.scheduled_time, outFormatter.format(
|
||||
temp
|
||||
)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
tvClientDenomination.text = order.clientContactName
|
||||
tvOrderScheduledTime.text =
|
||||
context.resources.getString(R.string.scheduled_time_error)
|
||||
}
|
||||
|
||||
if (order.getClientContactCellphone.trim().isNotEmpty()) {
|
||||
tvContact.text = order.clientContactName
|
||||
tvContactPhone.text = context.resources.getString(
|
||||
R.string.contact_phone, PhoneNumberUtils.formatNumber(
|
||||
order.getClientContactCellphone,
|
||||
"MX"
|
||||
)
|
||||
)
|
||||
tvContactPhone.visibility = View.VISIBLE
|
||||
} else {
|
||||
tvContact.text = order.clientContactName
|
||||
tvContactPhone.visibility = View.GONE
|
||||
}
|
||||
|
||||
if (order.comments != null) {
|
||||
linearComments.visibility = View.VISIBLE
|
||||
tvComments.text = order.comments
|
||||
} else
|
||||
linearComments.visibility = View.GONE
|
||||
|
||||
tvOrderName.text = order.serviceName
|
||||
tvServiceStatus.text = order.serviceStatusName
|
||||
tvPayMethod.text = order.payMethodName
|
||||
tvVehicle.text = order.vehicleCodeName
|
||||
tvOrderId.text = "${order.idRequest}"
|
||||
tvCost.text = context.resources.getString(R.string.cost, order.cost.currencyFormat())
|
||||
tvAddress.text = context.resources.getString(
|
||||
R.string.address,
|
||||
order.streetAddress,
|
||||
order.extNumberAddress,
|
||||
order.neighborhoodNameAddress,
|
||||
order.clientPostalCodeAddress
|
||||
)
|
||||
|
||||
val drawable = StatusDrawable(order.serviceStatusColor1, order.serviceStatusColor2)
|
||||
tvTitle.background = drawable
|
||||
|
||||
linearContact.setOnLongClickListener {
|
||||
if (order.getClientContactCellphone.trim().isNotEmpty()) {
|
||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions((itemView.context as AppCompatActivity), arrayOf(Manifest.permission.CALL_PHONE), 3)
|
||||
return@setOnLongClickListener true
|
||||
} else {
|
||||
val callIntent = Intent(Intent.ACTION_CALL)
|
||||
callIntent.data = Uri.parse("tel:" + order.getClientContactCellphone.trim()) // change the number
|
||||
vibrate()
|
||||
context.startActivity(callIntent)
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun vibrate() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
val vibratorManager = context.getSystemService(AppCompatActivity.VIBRATOR_MANAGER_SERVICE) as VibratorManager
|
||||
vibratorManager.defaultVibrator.vibrate(VibrationEffect.createOneShot(150, VibrationEffect.DEFAULT_AMPLITUDE))
|
||||
}else{
|
||||
(context.getSystemService(VIBRATOR_SERVICE) as Vibrator).vibrate(VibrationEffect.createOneShot(150, VibrationEffect.DEFAULT_AMPLITUDE))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.iesoluciones.siodrenax.adapters
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.ViewholderOperatorBinding
|
||||
import com.iesoluciones.siodrenax.entities.Operator
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
|
||||
class OperatorAdapter(
|
||||
var operatorList: List<Operator>,
|
||||
private val listener: OnOperatorSelectedListener
|
||||
|
||||
) : RecyclerView.Adapter<OperatorAdapter.ViewHolder>() {
|
||||
|
||||
interface OnOperatorSelectedListener {
|
||||
fun onOperatorClicked(operator: Operator)
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val binding =
|
||||
ViewholderOperatorBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(binding, listener)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(operatorList[position], position%2 == 0)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return operatorList.size
|
||||
}
|
||||
|
||||
class ViewHolder(
|
||||
val binding: ViewholderOperatorBinding,
|
||||
val listener: OnOperatorSelectedListener
|
||||
): RecyclerView.ViewHolder(binding.root){
|
||||
|
||||
private val tvInitials = binding.tvInitials
|
||||
private val tvName = binding.tvName
|
||||
private val tvOrdersIndicator = binding.tvOrdersIndicator
|
||||
private val cardOperator = binding.cardOperator
|
||||
|
||||
fun bind(operator: Operator, colorFlag: Boolean) = with(itemView){
|
||||
tvName.text = "${operator.name} ${operator.lastName} ${operator.mothersName}"
|
||||
|
||||
tvOrdersIndicator.text = "${operator.pendingOrders} / ${operator.totalOrders}"
|
||||
|
||||
tvInitials.text = HelperUtil().getInitials(
|
||||
operator.name,
|
||||
operator.lastName
|
||||
)
|
||||
|
||||
if (operator.pendingOrders == 0L) cardOperator.setCardBackgroundColor(
|
||||
itemView.context.resources.getColor(
|
||||
R.color.lightDarkGray
|
||||
)
|
||||
) else cardOperator.setCardBackgroundColor(itemView.context.resources.getColor(android.R.color.white))
|
||||
|
||||
if (colorFlag) tvInitials.setBackgroundResource(R.drawable.circle_border_accent) else tvInitials.setBackgroundResource(
|
||||
R.drawable.circle_border_primary
|
||||
)
|
||||
|
||||
itemView.setOnClickListener { listener.onOperatorClicked(operator) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
package com.iesoluciones.siodrenax.adapters
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Context.VIBRATOR_SERVICE
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
import android.os.VibratorManager
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.activities.OrderProgressActivity
|
||||
import com.iesoluciones.siodrenax.databinding.ViewholderOrderBinding
|
||||
import com.iesoluciones.siodrenax.entities.Order
|
||||
import com.iesoluciones.siodrenax.entities.OrderProgress
|
||||
import com.iesoluciones.siodrenax.repositories.OrdersRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.ORDER_ID
|
||||
import com.iesoluciones.siodrenax.utils.StatusDrawable
|
||||
import com.iesoluciones.siodrenax.utils.currencyFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class OrdersAdapter(
|
||||
private val context: Context,
|
||||
var orders: List<Order>
|
||||
) : RecyclerView.Adapter<OrdersAdapter.ViewHolder>() {
|
||||
|
||||
companion object{
|
||||
val inFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||
val outFormatter = SimpleDateFormat("HH:mm", Locale.getDefault())
|
||||
val ordersRepository: OrdersRepository = OrdersRepository()
|
||||
}
|
||||
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val binding =
|
||||
ViewholderOrderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(binding, context)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(orders[position])
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return orders.size
|
||||
}
|
||||
|
||||
class ViewHolder(
|
||||
val binding: ViewholderOrderBinding,
|
||||
val context: Context
|
||||
): RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
private val tvClientDenomination = binding.tvClientDenomination
|
||||
private val tvOrderName = binding.tvOrderName
|
||||
private val tvPayMethod = binding.tvPayMethod
|
||||
private val tvContact = binding.tvContact
|
||||
private val tvAddress = binding.tvAddress
|
||||
private val tvServiceStatus = binding.tvServiceStatus
|
||||
private val tvTitle = binding.tvTitle
|
||||
private val tvCost = binding.tvCost
|
||||
private val tvOrderId = binding.tvOrderId
|
||||
private val tvOrderScheduledTime = binding.tvOrderScheduledTime
|
||||
private val tvContactPhone = binding.tvContactPhone
|
||||
private val linearContact = binding.linearContact
|
||||
private val linearComments = binding.linearComments
|
||||
private val tvComments = binding.tvComments
|
||||
private val tvVehicle = binding.tvVehicle
|
||||
|
||||
fun bind(order: Order) = with(itemView){
|
||||
try {
|
||||
// NullPointerException launched once. The "dateServiceRequest" is a non null field.
|
||||
// The WS sends the field and the Local Data Base saves it properly
|
||||
// Commented to track the error -------------> Incidents = 1
|
||||
val temp: Date = inFormatter.parse(order.dateServiceRequest)!!
|
||||
tvClientDenomination.text = order.clientDenomination
|
||||
tvOrderScheduledTime.text = context.resources.getString(
|
||||
R.string.scheduled_time, outFormatter.format(
|
||||
temp
|
||||
)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
tvClientDenomination.text = order.clientContactName
|
||||
tvOrderScheduledTime.text = context.resources.getString(R.string.scheduled_time_error)
|
||||
}
|
||||
|
||||
tvOrderName.text = order.serviceName
|
||||
|
||||
val orderProgress: OrderProgress? = ordersRepository.getOrderProgressById(order.id)
|
||||
tvServiceStatus.text = if(orderProgress != null) context.getString(R.string.sincronizando) else order.serviceStatusName
|
||||
tvVehicle.text = order.vehicleCodeName
|
||||
|
||||
|
||||
if (order.getClientContactCellphone.trim().isNotEmpty()) {
|
||||
tvContact.text = order.clientContactName
|
||||
tvContactPhone.text = context.resources.getString(
|
||||
R.string.contact_phone, PhoneNumberUtils.formatNumber(
|
||||
order.getClientContactCellphone,
|
||||
"MX"
|
||||
)
|
||||
)
|
||||
tvContactPhone.visibility = View.VISIBLE
|
||||
} else {
|
||||
tvContact.text = order.clientContactName
|
||||
tvContactPhone.visibility = View.GONE
|
||||
}
|
||||
|
||||
tvPayMethod.text = order.payMethodName
|
||||
|
||||
val drawable = StatusDrawable(order.serviceStatusColor1, order.serviceStatusColor2)
|
||||
|
||||
tvTitle.background = drawable
|
||||
|
||||
tvOrderId.text = "${order.idRequest}"
|
||||
|
||||
tvCost.text = context.resources.getString(R.string.cost, order.cost.currencyFormat())
|
||||
|
||||
tvAddress.text = context.resources.getString(
|
||||
R.string.address,
|
||||
order.streetAddress,
|
||||
order.extNumberAddress,
|
||||
order.neighborhoodNameAddress,
|
||||
order.clientPostalCodeAddress
|
||||
)
|
||||
|
||||
if (order.comments != null) {
|
||||
linearComments.visibility = View.VISIBLE
|
||||
tvComments.text = order.comments
|
||||
} else linearComments.visibility = View.GONE
|
||||
|
||||
linearContact.setOnLongClickListener {
|
||||
if (order.getClientContactCellphone.trim().isNotEmpty()) {
|
||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions((itemView.context as AppCompatActivity), arrayOf(Manifest.permission.CALL_PHONE), 3)
|
||||
return@setOnLongClickListener true
|
||||
}else{
|
||||
val callIntent = Intent(Intent.ACTION_CALL)
|
||||
callIntent.data = Uri.parse("tel:" + order.getClientContactCellphone.trim()) // change the number
|
||||
vibrate()
|
||||
context.startActivity(callIntent)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
linearContact.setOnClickListener {
|
||||
//Se agrega por error en Crashlytics
|
||||
val orderRepo: Order? = ordersRepository.getOrderById(order.id)
|
||||
//Se agrega por error en Crashlytics
|
||||
if (orderRepo != null) {
|
||||
changeToOrderProgressActivity(order.id)
|
||||
} else {
|
||||
Toast.makeText(context, "No se encontró la información.", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
itemView.setOnClickListener {
|
||||
//Se agrega por error en Crashlytics
|
||||
val orderRepo: Order? = ordersRepository.getOrderById(order.id)
|
||||
//Se agrega por error en Crashlytics
|
||||
if (orderRepo != null) {
|
||||
changeToOrderProgressActivity(order.id)
|
||||
} else {
|
||||
Toast.makeText(context, "No se encontró la información.", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeToOrderProgressActivity(orderId: Long){
|
||||
val i = Intent(context, OrderProgressActivity::class.java)
|
||||
i.putExtra(ORDER_ID, orderId)
|
||||
context.startActivity(i)
|
||||
(context as AppCompatActivity).overridePendingTransition(
|
||||
R.anim.slide_in_rigth_airbnb,
|
||||
R.anim.scale_out_airbnb
|
||||
)
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun vibrate() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
val vibratorManager = context.getSystemService(AppCompatActivity.VIBRATOR_MANAGER_SERVICE) as VibratorManager
|
||||
vibratorManager.defaultVibrator.vibrate(VibrationEffect.createOneShot(150, VibrationEffect.DEFAULT_AMPLITUDE))
|
||||
}else{
|
||||
(context.getSystemService(VIBRATOR_SERVICE) as Vibrator).vibrate(VibrationEffect.createOneShot(150, VibrationEffect.DEFAULT_AMPLITUDE))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.iesoluciones.siodrenax.adapters
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
import android.os.VibratorManager
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.ViewholderOrderBinding
|
||||
import com.iesoluciones.siodrenax.entities.Order
|
||||
import com.iesoluciones.siodrenax.utils.StatusDrawable
|
||||
import com.iesoluciones.siodrenax.utils.currencyFormat
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class OrdersManagerAdapter(
|
||||
private val context: Context,
|
||||
var orders: List<Order>
|
||||
) : RecyclerView.Adapter<OrdersManagerAdapter.ViewHolder>() {
|
||||
|
||||
companion object{
|
||||
var inFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||
var outFormatter = SimpleDateFormat("HH:mm", Locale.getDefault())
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val binding =
|
||||
ViewholderOrderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(binding, context)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(orders[position])
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return orders.size
|
||||
}
|
||||
|
||||
class ViewHolder(
|
||||
val binding: ViewholderOrderBinding,
|
||||
val context: Context
|
||||
): RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
fun bind(order: Order){
|
||||
try {
|
||||
val temp: Date = inFormatter.parse(order.dateServiceRequest)!!
|
||||
binding.tvClientDenomination.text = order.clientDenomination
|
||||
binding.tvOrderScheduledTime.text = context.resources.getString(
|
||||
R.string.scheduled_time, outFormatter.format(
|
||||
temp
|
||||
)
|
||||
)
|
||||
} catch (e: ParseException) {
|
||||
e.printStackTrace()
|
||||
binding.tvClientDenomination.text = order.clientContactName
|
||||
binding.tvOrderScheduledTime.text = context.resources.getString(R.string.scheduled_time_error)
|
||||
}
|
||||
|
||||
binding.tvOrderName.text = order.serviceName
|
||||
binding.tvServiceStatus.text = order.serviceStatusName
|
||||
|
||||
if (order.getClientContactCellphone.trim().isNotEmpty()) {
|
||||
binding.tvContact.text = order.clientContactName
|
||||
binding.tvContactPhone.text = context.resources.getString(
|
||||
R.string.contact_phone, PhoneNumberUtils.formatNumber(
|
||||
order.getClientContactCellphone,
|
||||
"MX"
|
||||
)
|
||||
)
|
||||
binding.tvContactPhone.visibility = View.VISIBLE
|
||||
} else {
|
||||
binding.tvContact.text = order.clientContactName
|
||||
binding.tvContactPhone.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.tvPayMethod.text = order.payMethodName
|
||||
|
||||
val drawable = StatusDrawable(order.serviceStatusColor1, order.serviceStatusColor2)
|
||||
|
||||
binding.tvTitle.background = drawable
|
||||
|
||||
binding.tvVehicle.text = order.vehicleCodeName
|
||||
|
||||
binding.tvOrderId.text = "${order.idRequest}"
|
||||
|
||||
binding.tvCost.text = context.resources.getString(
|
||||
R.string.cost,
|
||||
order.cost.currencyFormat()
|
||||
)
|
||||
|
||||
binding.tvAddress.text = context.resources.getString(
|
||||
R.string.address,
|
||||
order.streetAddress,
|
||||
order.extNumberAddress,
|
||||
order.neighborhoodNameAddress,
|
||||
order.clientPostalCodeAddress
|
||||
)
|
||||
|
||||
if (order.comments != null) {
|
||||
binding.linearComments.visibility = View.VISIBLE
|
||||
binding.tvComments.text = order.comments
|
||||
} else binding.linearComments.visibility = View.GONE
|
||||
|
||||
binding.linearContact.setOnLongClickListener {
|
||||
if (order.getClientContactCellphone.trim().isNotEmpty()) {
|
||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions((itemView.context as AppCompatActivity), arrayOf(Manifest.permission.CALL_PHONE), 3)
|
||||
return@setOnLongClickListener true
|
||||
}else{
|
||||
val callIntent = Intent(Intent.ACTION_CALL)
|
||||
callIntent.data = Uri.parse("tel:" + order.getClientContactCellphone.trim()) // change the number
|
||||
vibrate()
|
||||
context.startActivity(callIntent)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun vibrate() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
val vibratorManager = context.getSystemService(AppCompatActivity.VIBRATOR_MANAGER_SERVICE) as VibratorManager
|
||||
vibratorManager.defaultVibrator.vibrate(VibrationEffect.createOneShot(150, VibrationEffect.DEFAULT_AMPLITUDE))
|
||||
}else{
|
||||
(context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator).vibrate(VibrationEffect.createOneShot(150, VibrationEffect.DEFAULT_AMPLITUDE))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.iesoluciones.siodrenax.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.siodrenax.databinding.ViewholderPdfBinding
|
||||
|
||||
class PdfViewerAdapter(
|
||||
private val context: Context,
|
||||
var pages: List<Bitmap>
|
||||
): RecyclerView.Adapter<PdfViewerAdapter.ViewHolder>() {
|
||||
|
||||
class ViewHolder(
|
||||
val binding: ViewholderPdfBinding,
|
||||
val context: Context
|
||||
): RecyclerView.ViewHolder(binding.root), View.OnTouchListener {
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
fun bind(bitmap: Bitmap) = with(itemView){
|
||||
val imageView: ImageView = binding.imageView
|
||||
imageView.setImageBitmap(bitmap)
|
||||
imageView.setOnTouchListener(this@ViewHolder)
|
||||
}
|
||||
|
||||
override fun onTouch(view: View?, motionEvent: MotionEvent?): Boolean {
|
||||
if(motionEvent!!.pointerCount >= 2 || (view!!.canScrollHorizontally(1) && view.canScrollHorizontally(-1))){
|
||||
when (motionEvent.action){
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
view!!.parent.requestDisallowInterceptTouchEvent(true)
|
||||
}
|
||||
MotionEvent.ACTION_UP -> {
|
||||
view!!.parent.requestDisallowInterceptTouchEvent(false)
|
||||
}
|
||||
else -> {return true}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val binding = ViewholderPdfBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(binding, context)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(pages[position])
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return pages.size
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package com.iesoluciones.siodrenax.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.OnFocusChangeListener
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Button
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.iesoluciones.siodrenax.App.Companion.context
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.checkListQuestionBox
|
||||
import com.iesoluciones.siodrenax.databinding.ViewholderRevisionBinding
|
||||
import com.iesoluciones.siodrenax.entities.CheckListQuestion
|
||||
import com.iesoluciones.siodrenax.entities.CheckListQuestion_
|
||||
import com.iesoluciones.siodrenax.repositories.CheckListRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants
|
||||
import io.objectbox.android.AndroidScheduler
|
||||
import io.objectbox.kotlin.equal
|
||||
import io.objectbox.reactive.DataSubscription
|
||||
|
||||
class RevisionSurveyAdapter(
|
||||
private val btnSiguiente: Button,
|
||||
private var checkListQuestionList: List<CheckListQuestion>,
|
||||
private val vehicle: List<String>,
|
||||
private val vehicleIds: List<Long>
|
||||
) : RecyclerView.Adapter<RevisionSurveyAdapter.ViewHolder>() {
|
||||
|
||||
companion object {
|
||||
var vehicleSelectedId: Long = 0
|
||||
}
|
||||
|
||||
var checkListQuestionBoxObserve: DataSubscription? = null
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
super.onAttachedToRecyclerView(recyclerView)
|
||||
|
||||
checkListQuestionBoxObserve = checkListQuestionBox.query(
|
||||
CheckListQuestion_.tipo equal Constants.REVISION
|
||||
)
|
||||
.build()
|
||||
.subscribe()
|
||||
.on(AndroidScheduler.mainThread())
|
||||
.observer { checkListQuestion -> checkListQuestionList = checkListQuestion }
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val binding =
|
||||
ViewholderRevisionBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return ViewHolder(binding, vehicle, vehicleIds)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, i: Int) {
|
||||
holder.bind(btnSiguiente, checkListQuestionList[i])
|
||||
}
|
||||
|
||||
override fun getItemCount() = checkListQuestionList.size
|
||||
|
||||
class ViewHolder(
|
||||
var binding: ViewholderRevisionBinding,
|
||||
private val vehicle: List<String>,
|
||||
val vehicleIds: List<Long>
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
var isSpinnerTouched = false
|
||||
|
||||
fun bind(btnSiguiente: Button, checkListQuestion: CheckListQuestion) = with(itemView) {
|
||||
|
||||
binding.radioGroup.visibility =
|
||||
if (checkListQuestion.tipoRadioBtn == 1) View.VISIBLE else View.GONE
|
||||
|
||||
binding.eTComentario.visibility =
|
||||
if (checkListQuestion.tipoText == 1) View.VISIBLE else View.GONE
|
||||
|
||||
binding.spVehiculos.visibility =
|
||||
if (checkListQuestion.id == 1L) View.VISIBLE else View.GONE
|
||||
|
||||
val isTipoSpinner =
|
||||
checkListQuestion.tipoCheckBox == 0 && checkListQuestion.tipoRadioBtn == 0 && checkListQuestion.tipoText == 0
|
||||
if (isTipoSpinner) {
|
||||
val dataAdapter: ArrayAdapter<String> = ArrayAdapter<String>(
|
||||
context,
|
||||
android.R.layout.simple_spinner_item,
|
||||
vehicle
|
||||
)
|
||||
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
binding.spVehiculos.adapter = dataAdapter
|
||||
if (checkListQuestion.respuestaText != "") {
|
||||
for (i in vehicle.indices) {
|
||||
if (vehicle[i] == checkListQuestion.respuestaText) {
|
||||
binding.spVehiculos.setSelection(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemView.tag = checkListQuestion.id
|
||||
binding.tvQuestionTitle.text = checkListQuestion.nombre
|
||||
binding.eTComentario.setText(checkListQuestion.respuestaText)
|
||||
val radioCheck: String? = checkListQuestion.respuestaRadioBtn
|
||||
if (radioCheck != null && itemView.tag == checkListQuestion.id) {
|
||||
|
||||
binding.radioNormal.tag = checkListQuestion.id
|
||||
binding.radioBajo.tag = checkListQuestion.id
|
||||
|
||||
if (radioCheck == context.getString(R.string.normal)) {
|
||||
binding.radioGroup.check(R.id.radioNormal)
|
||||
} else if (radioCheck == context.getString(R.string.bajo)) {
|
||||
binding.radioGroup.check(R.id.radioBajo)
|
||||
}
|
||||
}
|
||||
|
||||
listeners(isTipoSpinner, btnSiguiente)
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun listeners(isTipoSpinner: Boolean, btnSiguiente: Button) {
|
||||
val id = itemView.tag.toString().toLong()
|
||||
val objCheck: CheckListQuestion = checkListQuestionBox.get(id)
|
||||
|
||||
if(objCheck.tipoText == 1){
|
||||
binding.eTComentario.onFocusChangeListener = OnFocusChangeListener { _, hasFocus ->
|
||||
if (!hasFocus) {
|
||||
objCheck.respuestaText = (binding.eTComentario.text.toString())
|
||||
checkListQuestionBox.put(objCheck)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(objCheck.tipoRadioBtn == 1){
|
||||
binding.radioBajo.setOnClickListener {
|
||||
setCheckListText(objCheck, btnSiguiente, context!!.getString(R.string.bajo))
|
||||
}
|
||||
|
||||
binding.radioNormal.setOnClickListener {
|
||||
setCheckListText(objCheck, btnSiguiente, context!!.getString(R.string.normal))
|
||||
}
|
||||
}
|
||||
|
||||
if (isTipoSpinner) {
|
||||
btnSiguiente.visibility = if (CheckListRepository().isValidRevision() && binding.spVehiculos.selectedItemPosition != 0) View.VISIBLE else View.GONE
|
||||
binding.spVehiculos.setOnTouchListener { _, _ ->
|
||||
isSpinnerTouched = true
|
||||
false
|
||||
}
|
||||
|
||||
binding.spVehiculos.onItemSelectedListener =
|
||||
object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(
|
||||
parent: AdapterView<*>,
|
||||
view: View,
|
||||
position: Int,
|
||||
id: Long
|
||||
) {
|
||||
vehicleSelectedId = vehicleIds[position]
|
||||
if (isSpinnerTouched) {
|
||||
val item = parent.getItemAtPosition(position).toString()
|
||||
objCheck.respuestaText = (if (position != 0) item else "")
|
||||
checkListQuestionBox.put(objCheck)
|
||||
isSpinnerTouched = false
|
||||
btnSiguiente.visibility = if (CheckListRepository().isValidRevision() && vehicleSelectedId != 0L) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setCheckListText(objCheck:CheckListQuestion, btnSiguiente:Button, text:String){
|
||||
objCheck.respuestaRadioBtn = text
|
||||
checkListQuestionBox.put(objCheck)
|
||||
btnSiguiente.visibility = if (CheckListRepository().isValidRevision() && vehicleSelectedId != 0L) View.VISIBLE else View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
holder.binding.radioGroup.setOnCheckedChangeListener(null)
|
||||
holder.binding.spVehiculos.onItemSelectedListener = null
|
||||
holder.binding.radioGroup.clearCheck()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.iesoluciones.siodrenax.models.Answer
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
import io.objectbox.annotation.NameInDb
|
||||
|
||||
@Entity
|
||||
data class BusinessAnswer(
|
||||
@Id(assignable = true)
|
||||
private var id: Long,
|
||||
|
||||
@NameInDb("pregunta_id")
|
||||
@SerializedName("pregunta_id")
|
||||
private var idQuestion: Long,
|
||||
|
||||
@NameInDb("nombre")
|
||||
@SerializedName("nombre")
|
||||
private var title: String,
|
||||
|
||||
@NameInDb("orden")
|
||||
@SerializedName("orden")
|
||||
private var order: Int,
|
||||
|
||||
@NameInDb("tipo_campo")
|
||||
@SerializedName("tipo_campo")
|
||||
private var type: String,
|
||||
|
||||
): Answer() {
|
||||
override fun getId(): Long {
|
||||
return id
|
||||
}
|
||||
|
||||
override fun getIdQuestion(): Long {
|
||||
return idQuestion
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return title
|
||||
}
|
||||
|
||||
override fun getOrder(): Int {
|
||||
return order
|
||||
}
|
||||
|
||||
override fun getType(): String {
|
||||
return type
|
||||
}
|
||||
|
||||
fun setId(id: Long){
|
||||
this.id = id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.iesoluciones.siodrenax.models.Question
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
import io.objectbox.annotation.NameInDb
|
||||
|
||||
@Entity
|
||||
data class BusinessQuestion(
|
||||
@Id(assignable = true)
|
||||
private var id: Long,
|
||||
|
||||
@NameInDb("nombre")
|
||||
@SerializedName("nombre")
|
||||
private var title: String,
|
||||
|
||||
@NameInDb("orden")
|
||||
@SerializedName("orden")
|
||||
private var order: Int,
|
||||
|
||||
@NameInDb("mostrar_numero")
|
||||
@SerializedName("mostrar_numero")
|
||||
private var showNumber: Int,
|
||||
|
||||
@NameInDb("obligatorio")
|
||||
@SerializedName("obligatorio")
|
||||
private var required: Boolean,
|
||||
|
||||
): Question() {
|
||||
override fun getId(): Long {
|
||||
return id
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return title
|
||||
}
|
||||
|
||||
override fun getOrder(): Int {
|
||||
return order
|
||||
}
|
||||
|
||||
override fun getShowNumber(): Int {
|
||||
return showNumber
|
||||
}
|
||||
|
||||
override fun getRequired(): Boolean {
|
||||
return required
|
||||
}
|
||||
|
||||
fun setId(id: Long){
|
||||
this.id = id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
import io.objectbox.annotation.NameInDb
|
||||
import javax.annotation.Nullable
|
||||
|
||||
@Entity
|
||||
data class CheckListQuestion(
|
||||
@Id(assignable = true)
|
||||
var id: Long,
|
||||
|
||||
var nombre: String,
|
||||
|
||||
@NameInDb("tipo_radio_btn")
|
||||
@SerializedName("tipo_radio_btn")
|
||||
var tipoRadioBtn: Int,
|
||||
|
||||
@NameInDb("tipo_text")
|
||||
@SerializedName("tipo_text")
|
||||
var tipoText: Int,
|
||||
|
||||
@NameInDb("tipo_checkbox")
|
||||
@SerializedName("tipo_checkbox")
|
||||
var tipoCheckBox: Int,
|
||||
|
||||
@NameInDb("tipo")
|
||||
@SerializedName("tipo")
|
||||
var tipo: String,
|
||||
|
||||
@Nullable
|
||||
@NameInDb("respuesta_radio_btn")
|
||||
@SerializedName("respuesta_radio_btn")
|
||||
var respuestaRadioBtn: String? = null,
|
||||
|
||||
@Nullable
|
||||
@NameInDb("respuesta_text")
|
||||
@SerializedName("respuesta_text")
|
||||
var respuestaText: String? = null,
|
||||
|
||||
@Nullable
|
||||
@NameInDb("respuesta_checkbox")
|
||||
@SerializedName("respuesta_checkbox")
|
||||
var respuestaCheckBox: Boolean = false,
|
||||
|
||||
@Nullable
|
||||
@NameInDb("fecha")
|
||||
@SerializedName("fecha")
|
||||
var fecha: String
|
||||
)
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.iesoluciones.siodrenax.models.Answer
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
import io.objectbox.annotation.NameInDb
|
||||
|
||||
@Entity
|
||||
data class DomesticAnswer(
|
||||
@Id(assignable = true)
|
||||
private var id: Long,
|
||||
|
||||
@NameInDb("pregunta_id")
|
||||
@SerializedName("pregunta_id")
|
||||
private var idQuestion: Long,
|
||||
|
||||
@NameInDb("nombre")
|
||||
@SerializedName("nombre")
|
||||
private var title: String,
|
||||
|
||||
@NameInDb("orden")
|
||||
@SerializedName("orden")
|
||||
private var order: Int,
|
||||
|
||||
@NameInDb("tipo_campo")
|
||||
@SerializedName("tipo_campo")
|
||||
private var type: String,
|
||||
): Answer() {
|
||||
override fun getId(): Long {
|
||||
return id
|
||||
}
|
||||
|
||||
override fun getIdQuestion(): Long {
|
||||
return idQuestion
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return title
|
||||
}
|
||||
|
||||
override fun getOrder(): Int {
|
||||
return order
|
||||
}
|
||||
|
||||
override fun getType(): String {
|
||||
return type
|
||||
}
|
||||
fun setId(id: Long){
|
||||
this.id = id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.iesoluciones.siodrenax.models.Question
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
import io.objectbox.annotation.NameInDb
|
||||
|
||||
@Entity
|
||||
class DomesticQuestion(
|
||||
@Id(assignable = true)
|
||||
private var id: Long,
|
||||
|
||||
@NameInDb("nombre")
|
||||
@SerializedName("nombre")
|
||||
private var title: String,
|
||||
|
||||
@NameInDb("orden")
|
||||
@SerializedName("orden")
|
||||
private var order: Int,
|
||||
|
||||
@NameInDb("mostrar_numero")
|
||||
@SerializedName("mostrar_numero")
|
||||
private var showNumber: Int,
|
||||
|
||||
@NameInDb("obligatorio")
|
||||
@SerializedName("obligatorio")
|
||||
private var required: Boolean,
|
||||
|
||||
):Question() {
|
||||
override fun getId(): Long {
|
||||
return id
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return title
|
||||
}
|
||||
|
||||
override fun getOrder(): Int {
|
||||
return order
|
||||
}
|
||||
|
||||
override fun getShowNumber(): Int {
|
||||
return showNumber
|
||||
}
|
||||
|
||||
override fun getRequired(): Boolean {
|
||||
return required
|
||||
}
|
||||
|
||||
fun setId(id: Long){
|
||||
this.id = id
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.DEFAULT_LATITUDE
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.DEFAULT_LONGITUDE
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.EVIDENCE_FINAL
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.EVIDENCE_PROCESS
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.EVIDENCE_START
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
|
||||
@Entity
|
||||
data class Evidence(
|
||||
@Id
|
||||
var id: Long,
|
||||
var evidenceNo: Long,
|
||||
var idOrder: Long,
|
||||
var idRequest: Long,
|
||||
var type: Int,
|
||||
var path: String?,
|
||||
var name: String?,
|
||||
var lat: String,
|
||||
var lng: String,
|
||||
var viewRef: Int,
|
||||
var isSent: Boolean
|
||||
){
|
||||
constructor() : this(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
DEFAULT_LATITUDE.toString(),
|
||||
DEFAULT_LONGITUDE.toString(),
|
||||
0,
|
||||
false
|
||||
)
|
||||
|
||||
fun getTypeDescription(): String {
|
||||
return when (this.type) {
|
||||
EVIDENCE_START -> "Inicio"
|
||||
EVIDENCE_PROCESS -> "Proceso"
|
||||
EVIDENCE_FINAL -> "Final"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import com.iesoluciones.siodrenax.models.Reason
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
|
||||
@Entity
|
||||
data class NegativeServiceReason(
|
||||
@Id(assignable = true)
|
||||
private var id: Long,
|
||||
private var descripcion: String
|
||||
|
||||
) : Reason() {
|
||||
override fun getId(): Long {
|
||||
return id
|
||||
}
|
||||
|
||||
override fun getTitle(): String {
|
||||
return descripcion
|
||||
}
|
||||
|
||||
fun setId(id: Long){
|
||||
this.id = id
|
||||
}
|
||||
|
||||
fun getDescripcion(): String{
|
||||
return descripcion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
|
||||
@Entity
|
||||
data class NextDayOrder (
|
||||
@Id(assignable = true)
|
||||
@SerializedName("id")
|
||||
var id: Long,
|
||||
|
||||
@SerializedName("servicio_id")
|
||||
var idService: Long,
|
||||
|
||||
@SerializedName("solicitud_servicio_id")
|
||||
var idRequest: Long,
|
||||
|
||||
@SerializedName("servicio_nombre")
|
||||
var serviceName: String,
|
||||
|
||||
@SerializedName("estatus_servicio_id")
|
||||
var idServiceStatus: Long,
|
||||
|
||||
@SerializedName("estatus_servicio_nombre")
|
||||
var serviceStatusName: String,
|
||||
|
||||
@SerializedName("estatus_servicio_color_1")
|
||||
var serviceStatusColor1: String,
|
||||
|
||||
@SerializedName("estatus_servicio_color_2")
|
||||
var serviceStatusColor2: String? = null,
|
||||
|
||||
@SerializedName("forma_pago_id")
|
||||
var idPayMethod: Long,
|
||||
|
||||
@SerializedName("forma_pago_nombre")
|
||||
var payMethodName: String,
|
||||
|
||||
@SerializedName("tipo_servicio_id")
|
||||
var idServiceType: Long,
|
||||
|
||||
@SerializedName("observacion_atencion_cliente")
|
||||
var comments: String?,
|
||||
|
||||
@SerializedName("costo_servicio")
|
||||
var cost: String,
|
||||
|
||||
@SerializedName("tipo_servicio_nombre")
|
||||
var serviceTypeName: String,
|
||||
|
||||
@SerializedName("fecha_agenda")
|
||||
var dateScheduled: String,
|
||||
|
||||
@SerializedName("fecha_solicitud")
|
||||
var dateServiceRequest: String,
|
||||
|
||||
@SerializedName("usuario_agenda_id")
|
||||
var idUserSchedule: Long,
|
||||
|
||||
@SerializedName("usuario_agenda_nombre")
|
||||
var userScheduleName: String,
|
||||
|
||||
@SerializedName("usuario_agenda_apellido_paterno")
|
||||
var userScheduleLastName: String,
|
||||
|
||||
@SerializedName("usuario_agenda_apellido_materno")
|
||||
var getUserScheduleMothersLastName: String,
|
||||
|
||||
@SerializedName("duracion")
|
||||
var duracion: String,
|
||||
|
||||
@SerializedName("definido_cliente")
|
||||
var clientDefined: Long,
|
||||
|
||||
@SerializedName("cliente_id")
|
||||
var idClient: Long,
|
||||
|
||||
@SerializedName("denominacion")
|
||||
var clientDenomination: String,
|
||||
|
||||
@SerializedName("clientes_nombre_responsable_sucursal")
|
||||
var clientContactName: String,
|
||||
|
||||
@SerializedName("clientes_celular_responsable")
|
||||
var getClientContactCellphone: String,
|
||||
|
||||
@SerializedName("cliente_domicilio_id")
|
||||
var idClientAddress: Long,
|
||||
|
||||
@SerializedName("clientes_calle")
|
||||
var streetAddress: String? = null,
|
||||
|
||||
@SerializedName("clientes_num_ext")
|
||||
var extNumberAddress: String? = null,
|
||||
|
||||
@SerializedName("clientes_num_int")
|
||||
var intNumberAddress: String? = null,
|
||||
|
||||
@SerializedName("clientes_colonia")
|
||||
var neighborhoodNameAddress: String? = null,
|
||||
|
||||
@SerializedName("clientes_cp")
|
||||
var clientPostalCodeAddress: String? = null,
|
||||
|
||||
@SerializedName("clientes_telefono")
|
||||
var clientPhone: String,
|
||||
|
||||
@SerializedName("clientes_lat")
|
||||
var clientLat: String,
|
||||
|
||||
@SerializedName("clientes_lng")
|
||||
var clientLng: String,
|
||||
|
||||
@SerializedName("operador_id")
|
||||
var idOperator: Long,
|
||||
|
||||
@SerializedName("operador_nombre")
|
||||
var operatorName: String,
|
||||
|
||||
@SerializedName("operador_apellido_paterno")
|
||||
var operatorLastName: String,
|
||||
|
||||
@SerializedName("operador_apellido_materno")
|
||||
var operatorMothersName: String,
|
||||
|
||||
@SerializedName("vehiculo_id")
|
||||
var idVehicle: Long,
|
||||
|
||||
@SerializedName("vehiculo_num_economico")
|
||||
var vehicleCodeName: String,
|
||||
|
||||
@SerializedName("vehiculo_sucursal")
|
||||
var vehicleOfficeName: String,
|
||||
|
||||
@SerializedName("vehiculo_sucursal_id")
|
||||
var idVehicleOffice: Long,
|
||||
|
||||
@SerializedName("operador_sucursal")
|
||||
var operatorOfficeName: String,
|
||||
|
||||
@SerializedName("operador_sucursal_id")
|
||||
var idOperatorOffice: Long,
|
||||
|
||||
@SerializedName("auxiliar_1_id")
|
||||
var idAssistant1: Long,
|
||||
|
||||
@SerializedName("auxiliar_2_id")
|
||||
var idAssistant2: Long,
|
||||
|
||||
@SerializedName("auxiliar_1")
|
||||
var assistant1Name: String? = null,
|
||||
|
||||
@SerializedName("auxiliar_2")
|
||||
var assistant2Name: String? = null,
|
||||
|
||||
@SerializedName("sucursal_auxiliar_1")
|
||||
var assistant1OfficeName: String? = null,
|
||||
|
||||
@SerializedName("sucursal_auxiliar_2")
|
||||
var assistant2OfficeName: String? = null,
|
||||
|
||||
@SerializedName("requiere_encuesta")
|
||||
var SurveyRequired: Int,
|
||||
|
||||
var isSent: Boolean,
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
import io.objectbox.annotation.NameInDb
|
||||
|
||||
@Entity
|
||||
data class Operator(
|
||||
@Id(assignable = true) var id: Long,
|
||||
|
||||
@NameInDb("nombre")
|
||||
@SerializedName("nombre")
|
||||
var name: String,
|
||||
|
||||
@NameInDb("apellido_paterno")
|
||||
@SerializedName("apellido_paterno")
|
||||
var lastName: String,
|
||||
|
||||
@NameInDb("apellido_materno")
|
||||
@SerializedName("apellido_materno")
|
||||
var mothersName: String,
|
||||
|
||||
@NameInDb("servicios_total")
|
||||
@SerializedName("servicios_total")
|
||||
var totalOrders: Long,
|
||||
|
||||
@NameInDb("servicios_pendiente")
|
||||
@SerializedName("servicios_pendiente")
|
||||
var pendingOrders: Long
|
||||
)
|
||||
190
app/src/main/java/com/iesoluciones/siodrenax/entities/Order.kt
Normal file
190
app/src/main/java/com/iesoluciones/siodrenax/entities/Order.kt
Normal file
@@ -0,0 +1,190 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
|
||||
@Entity
|
||||
data class Order (
|
||||
@Id(assignable = true)
|
||||
@SerializedName("id")
|
||||
var id: Long,
|
||||
|
||||
@SerializedName("servicio_id")
|
||||
var idService: Long,
|
||||
|
||||
@SerializedName("solicitud_servicio_id")
|
||||
var idRequest: Long,
|
||||
|
||||
@SerializedName("servicio_nombre")
|
||||
var serviceName: String,
|
||||
|
||||
@SerializedName("estatus_servicio_id")
|
||||
var idServiceStatus: Long,
|
||||
|
||||
@SerializedName("estatus_servicio_nombre")
|
||||
var serviceStatusName: String,
|
||||
|
||||
@SerializedName("estatus_servicio_color_1")
|
||||
var serviceStatusColor1: String,
|
||||
|
||||
@SerializedName("estatus_servicio_color_2")
|
||||
var serviceStatusColor2: String? = null,
|
||||
|
||||
@SerializedName("forma_pago_id")
|
||||
var idPayMethod: Long,
|
||||
|
||||
@SerializedName("forma_pago_nombre")
|
||||
var payMethodName: String,
|
||||
|
||||
@SerializedName("tipo_servicio_id")
|
||||
var idServiceType: Long,
|
||||
|
||||
@SerializedName("observacion_atencion_cliente")
|
||||
var comments: String?,
|
||||
|
||||
@SerializedName("costo_servicio")
|
||||
var cost: String,
|
||||
|
||||
@SerializedName("costo_servicio_negativo")
|
||||
var negativeCost: String,
|
||||
|
||||
@SerializedName("tipo_servicio_nombre")
|
||||
var serviceTypeName: String,
|
||||
|
||||
@SerializedName("fecha_agenda")
|
||||
var dateScheduled: String,
|
||||
|
||||
@SerializedName("fecha_solicitud")
|
||||
var dateServiceRequest: String,
|
||||
|
||||
@SerializedName("usuario_agenda_id")
|
||||
var idUserSchedule: Long,
|
||||
|
||||
@SerializedName("usuario_agenda_nombre")
|
||||
var userScheduleName: String,
|
||||
|
||||
@SerializedName("usuario_agenda_apellido_paterno")
|
||||
var userScheduleLastName: String,
|
||||
|
||||
@SerializedName("usuario_agenda_apellido_materno")
|
||||
var getUserScheduleMothersLastName: String,
|
||||
|
||||
@SerializedName("duracion")
|
||||
var duracion: String,
|
||||
|
||||
@SerializedName("definido_cliente")
|
||||
var clientDefined: Long,
|
||||
|
||||
@SerializedName("cliente_id")
|
||||
var idClient: Long,
|
||||
|
||||
@SerializedName("denominacion")
|
||||
var clientDenomination: String,
|
||||
|
||||
@SerializedName("clientes_nombre_responsable_sucursal")
|
||||
var clientContactName: String,
|
||||
|
||||
@SerializedName("clientes_celular_responsable")
|
||||
var getClientContactCellphone: String,
|
||||
|
||||
@SerializedName("cliente_domicilio_id")
|
||||
var idClientAddress: Long,
|
||||
|
||||
@SerializedName("clientes_calle")
|
||||
var streetAddress: String? = null,
|
||||
|
||||
@SerializedName("clientes_num_ext")
|
||||
var extNumberAddress: String? = null,
|
||||
|
||||
@SerializedName("clientes_num_int")
|
||||
var intNumberAddress: String? = null,
|
||||
|
||||
@SerializedName("clientes_colonia")
|
||||
var neighborhoodNameAddress: String? = null,
|
||||
|
||||
@SerializedName("clientes_cp")
|
||||
var clientPostalCodeAddress: String? = null,
|
||||
|
||||
@SerializedName("clientes_ciudad")
|
||||
var clientCity: String,
|
||||
|
||||
@SerializedName("clientes_telefono")
|
||||
var clientPhone: String,
|
||||
|
||||
@SerializedName("clientes_lat")
|
||||
var clientLat: String,
|
||||
|
||||
@SerializedName("clientes_lng")
|
||||
var clientLng: String,
|
||||
|
||||
@SerializedName("operador_id")
|
||||
var idOperator: Long,
|
||||
|
||||
@SerializedName("operador_nombre")
|
||||
var operatorName: String,
|
||||
|
||||
@SerializedName("operador_apellido_paterno")
|
||||
var operatorLastName: String,
|
||||
|
||||
@SerializedName("operador_apellido_materno")
|
||||
var operatorMothersName: String,
|
||||
|
||||
@SerializedName("vehiculo_id")
|
||||
var idVehicle: Long,
|
||||
|
||||
@SerializedName("vehiculo_num_economico")
|
||||
var vehicleCodeName: String,
|
||||
|
||||
@SerializedName("vehiculo_sucursal")
|
||||
var vehicleOfficeName: String,
|
||||
|
||||
@SerializedName("vehiculo_sucursal_id")
|
||||
var idVehicleOffice: Long,
|
||||
|
||||
@SerializedName("operador_sucursal")
|
||||
var operatorOfficeName: String,
|
||||
|
||||
@SerializedName("operador_sucursal_id")
|
||||
var idOperatorOffice: Long,
|
||||
|
||||
@SerializedName("auxiliar_1_id")
|
||||
var idAssistant1: Long,
|
||||
|
||||
@SerializedName("auxiliar_2_id")
|
||||
var idAssistant2: Long,
|
||||
|
||||
@SerializedName("auxiliar_1")
|
||||
var assistant1Name: String? = null,
|
||||
|
||||
@SerializedName("auxiliar_1_apellido_paterno")
|
||||
var assistant1LastName: String? = null,
|
||||
|
||||
@SerializedName("auxiliar_1_apellido_materno")
|
||||
var assistant1MothersName: String? = null,
|
||||
|
||||
@SerializedName("auxiliar_2")
|
||||
var assistant2Name: String? = null,
|
||||
|
||||
@SerializedName("sucursal_auxiliar_1")
|
||||
var assistant1OfficeName: String? = null,
|
||||
|
||||
@SerializedName("sucursal_auxiliar_2")
|
||||
var assistant2OfficeName: String? = null,
|
||||
|
||||
@SerializedName("requiere_encuesta")
|
||||
var SurveyRequired: Int,
|
||||
|
||||
var isSent: Boolean,
|
||||
|
||||
@SerializedName("pdf_path")
|
||||
var pdfPath: String?,
|
||||
|
||||
@SerializedName("nombre_croquis")
|
||||
var sketchName: String?,
|
||||
|
||||
var sketchPath: String?,
|
||||
|
||||
@SerializedName("nombre_sucursal")
|
||||
var branchName: String,
|
||||
)
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
|
||||
@Entity
|
||||
data class OrderProgress (
|
||||
|
||||
@Id(assignable = true)
|
||||
var id: Long,
|
||||
var idRequest: Long,
|
||||
var startDate: String,
|
||||
var endDate: String?,
|
||||
var comments: String?,
|
||||
var elapsedTime: String?,
|
||||
var startLat: String,
|
||||
var startLng: String,
|
||||
var endLat: String,
|
||||
var endLng: String,
|
||||
var signaturePath: String?,
|
||||
var signatureName: String?,
|
||||
var warranty: Boolean,
|
||||
var isSent: Boolean,
|
||||
var shouldBeSent: Boolean,
|
||||
var signatureSent: Boolean,
|
||||
var isOnSurvey: Boolean,
|
||||
var shouldSendSurvey: Boolean,
|
||||
var surveySent: Boolean,
|
||||
var liters: Int,
|
||||
var negativeService: Int,
|
||||
){
|
||||
constructor() : this(0,
|
||||
0,
|
||||
"",
|
||||
null,
|
||||
"",
|
||||
null,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
0
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
|
||||
@Entity
|
||||
data class SavedAnswer(
|
||||
@Id(assignable = true)
|
||||
var id: Long,
|
||||
var questionId: Long,
|
||||
var orderId: Long,
|
||||
var isOpen: Boolean,
|
||||
var answer: String?
|
||||
){
|
||||
constructor() : this(0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
null
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
import io.objectbox.annotation.NameInDb
|
||||
|
||||
@Entity
|
||||
data class User(
|
||||
@Id(assignable = true) var id: Long,
|
||||
var email: String,
|
||||
|
||||
@NameInDb("nombre")
|
||||
@SerializedName("nombre")
|
||||
var username: String,
|
||||
|
||||
@NameInDb("apellido_paterno")
|
||||
@SerializedName("apellido_paterno")
|
||||
var lastName: String,
|
||||
|
||||
@NameInDb("apellido_materno")
|
||||
@SerializedName("apellido_materno")
|
||||
var mothersName: String,
|
||||
|
||||
@NameInDb("telefono")
|
||||
@SerializedName("telefono")
|
||||
var phone: String,
|
||||
|
||||
@NameInDb("tipo_empleado_id")
|
||||
@SerializedName("tipo_empleado_id")
|
||||
var idEmployeeType: Long
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.iesoluciones.siodrenax.entities
|
||||
|
||||
import io.objectbox.annotation.Entity
|
||||
import io.objectbox.annotation.Id
|
||||
|
||||
@Entity
|
||||
data class Vehicle(
|
||||
@Id(assignable = true) var id: Long,
|
||||
var nombre: String
|
||||
)
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.iesoluciones.siodrenax.fragments.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.FragmentIncidentsInputBinding
|
||||
import com.iesoluciones.siodrenax.interfaces.OnIncidentListener
|
||||
|
||||
class IncidentsInputFragment : DialogFragment(){
|
||||
|
||||
private lateinit var _binding: FragmentIncidentsInputBinding
|
||||
private val binding get() = _binding
|
||||
lateinit var listener: OnIncidentListener
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
|
||||
_binding = FragmentIncidentsInputBinding.inflate(inflater, container, false)
|
||||
|
||||
binding.tvContinue.setOnClickListener { onClickTvContinue() }
|
||||
binding.tvCancel.setOnClickListener { onClickTvCancel() }
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
private fun onClickTvContinue() {
|
||||
val editIncident = binding.editIncident
|
||||
|
||||
if (isEmpty(editIncident)) {
|
||||
binding.labelIncident.error = getText(R.string.incident_dialog_error)
|
||||
listener.onIncidentInput(null)
|
||||
} else {
|
||||
listener.onIncidentInput(editIncident.text.toString().replace(",".toRegex(), ""))
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onClickTvCancel() {
|
||||
listener.onNoIncident()
|
||||
dismiss()
|
||||
}
|
||||
|
||||
override fun show(manager: FragmentManager, tag: String?) {
|
||||
try {
|
||||
val ft = manager.beginTransaction()
|
||||
ft.add(this, tag)
|
||||
ft.commitAllowingStateLoss()
|
||||
} catch (e: IllegalStateException) {
|
||||
Log.e("Exception", e.toString())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
|
||||
listener = if (activity is OnIncidentListener) {
|
||||
(activity as OnIncidentListener?)!!
|
||||
} else throw RuntimeException("Parent Activity not implementing OnIncidentListener")
|
||||
}
|
||||
|
||||
private fun isEmpty(incident: EditText): Boolean {
|
||||
return incident.text.toString().trim { it <= ' ' }.isEmpty() || incident.text == null
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(listener: OnIncidentListener): IncidentsInputFragment {
|
||||
val fragment = IncidentsInputFragment()
|
||||
fragment.listener = listener
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.iesoluciones.siodrenax.fragments.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.databinding.FragmentMileageInputDialogBinding
|
||||
import com.iesoluciones.siodrenax.interfaces.OnMileageListener
|
||||
import com.iesoluciones.siodrenax.utils.NumberFormatterTextWatcher
|
||||
|
||||
class MileageInputDialogFragment : DialogFragment() {
|
||||
|
||||
private lateinit var _binding: FragmentMileageInputDialogBinding
|
||||
private val binding get() = _binding
|
||||
lateinit var listener: OnMileageListener
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
_binding = FragmentMileageInputDialogBinding.inflate(inflater, container, false)
|
||||
val view = binding.root
|
||||
isCancelable = false
|
||||
binding.labelMileage.suffixText = getText(R.string.mileage_dialog_suffix)
|
||||
|
||||
binding.tvContinue.setOnClickListener {
|
||||
if (isEmpty(binding.editMileage)) {
|
||||
binding.labelMileage.error = getText(R.string.mileage_dialog_error)
|
||||
listener.onMileageInput(null)
|
||||
} else {
|
||||
listener.onMileageInput(
|
||||
binding.editMileage.text.toString().replace(",".toRegex(), "")
|
||||
)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
binding.tvCancel.setOnClickListener {
|
||||
dismiss()
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
binding.labelMileage.suffixText = getText(R.string.mileage_dialog_suffix)
|
||||
binding.editMileage.addTextChangedListener(NumberFormatterTextWatcher(binding.editMileage))
|
||||
}
|
||||
|
||||
override fun show(manager: FragmentManager, tag: String?) {
|
||||
try {
|
||||
val ft = manager.beginTransaction()
|
||||
ft.add(this, tag)
|
||||
ft.commitAllowingStateLoss()
|
||||
} catch (e: IllegalStateException) {
|
||||
Log.e("Exception", e.toString())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
listener = if (activity is OnMileageListener) {
|
||||
activity as OnMileageListener
|
||||
} else throw RuntimeException("Parent Activity not implementing OnMileageListener")
|
||||
}
|
||||
|
||||
private fun isEmpty(mileage: EditText?): Boolean {
|
||||
return mileage!!.text.toString().trim { it <= ' ' }.isEmpty() || mileage.text == null
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(listener: OnMileageListener): MileageInputDialogFragment {
|
||||
val fragment = MileageInputDialogFragment()
|
||||
fragment.listener = listener
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.iesoluciones.siodrenax.fragments.dialogs
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.iesoluciones.siodrenax.databinding.FragmentVehicleIncidentsBinding
|
||||
import com.iesoluciones.siodrenax.interfaces.OnIncidentShowListener
|
||||
|
||||
class VehicleIncidentsFragment : DialogFragment() {
|
||||
|
||||
private lateinit var _binding: FragmentVehicleIncidentsBinding
|
||||
private val binding get() = _binding
|
||||
lateinit var listener: OnIncidentShowListener
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
_binding = FragmentVehicleIncidentsBinding.inflate(inflater, container, false)
|
||||
val view = binding.root
|
||||
|
||||
binding.tvIncidence.text = incidence
|
||||
isCancelable = false
|
||||
|
||||
binding.tvContinue.setOnClickListener{
|
||||
listener.onIncidenceSolved()
|
||||
dismiss()
|
||||
}
|
||||
|
||||
binding.tvCancel.setOnClickListener{
|
||||
listener.onIncidenceNotSolved()
|
||||
dismiss()
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
override fun show(manager: FragmentManager, tag: String?) {
|
||||
try {
|
||||
val ft = manager.beginTransaction()
|
||||
ft.add(this, tag)
|
||||
ft.commitAllowingStateLoss()
|
||||
} catch (e: IllegalStateException) {
|
||||
Log.e("Exception", e.toString())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
listener = if (activity is OnIncidentShowListener) {
|
||||
activity as OnIncidentShowListener
|
||||
} else throw RuntimeException("Parent Activity not implementing OnIncidentListener")
|
||||
}
|
||||
|
||||
companion object {
|
||||
var incidence: String? = null
|
||||
fun newInstance(listener: OnIncidentShowListener, incidence: String?): VehicleIncidentsFragment {
|
||||
val fragment = VehicleIncidentsFragment()
|
||||
fragment.listener = listener
|
||||
Companion.incidence = incidence
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.iesoluciones.siodrenax.interfaces
|
||||
|
||||
interface OnIncidentListener {
|
||||
fun onNoIncident()
|
||||
fun onIncidentInput(incident: String?)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.iesoluciones.siodrenax.interfaces
|
||||
|
||||
interface OnIncidentShowListener {
|
||||
fun onIncidenceSolved()
|
||||
fun onIncidenceNotSolved()
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.iesoluciones.siodrenax.interfaces
|
||||
|
||||
interface OnMileageListener {
|
||||
fun onMileageInput(mileage: String?)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
abstract class Answer {
|
||||
abstract fun getId(): Long
|
||||
abstract fun getIdQuestion(): Long
|
||||
abstract fun getTitle(): String
|
||||
abstract fun getOrder(): Int
|
||||
abstract fun getType(): String
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.iesoluciones.siodrenax.entities.BusinessAnswer
|
||||
import com.iesoluciones.siodrenax.entities.DomesticAnswer
|
||||
|
||||
data class AnswerPOJO(
|
||||
@SerializedName("id")
|
||||
var id: Long,
|
||||
|
||||
@SerializedName("pregunta_id")
|
||||
var idQuestion: Long,
|
||||
|
||||
@SerializedName("nombre")
|
||||
var title: String,
|
||||
|
||||
@SerializedName("orden")
|
||||
var order: Int,
|
||||
|
||||
@SerializedName("tipo_campo")
|
||||
var type: String,
|
||||
){
|
||||
fun getDomesticAnswer(): DomesticAnswer {
|
||||
return DomesticAnswer(id, idQuestion, title, order, type)
|
||||
}
|
||||
|
||||
fun getBusinessAnswer(): BusinessAnswer {
|
||||
return BusinessAnswer(id, idQuestion, title, order, type)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class CheckBoxAnswer (
|
||||
@SerializedName("pregunta_id")
|
||||
var questionId: String,
|
||||
|
||||
@SerializedName("respuesta_id")
|
||||
var answerId: String?
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class EvidenceRequest(
|
||||
|
||||
@SerializedName("nombre")
|
||||
var name: String,
|
||||
|
||||
@SerializedName("etapa")
|
||||
var stage: String,
|
||||
|
||||
@SerializedName("lat")
|
||||
var lat: String,
|
||||
|
||||
@SerializedName("lng")
|
||||
var lng: String,
|
||||
)
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
data class EvidenceSignatureLocal(
|
||||
var path: String?,
|
||||
var name: String?,
|
||||
)
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import javax.annotation.Nullable
|
||||
|
||||
data class FinishOrderRequest(
|
||||
|
||||
@SerializedName("servicio_det_id")
|
||||
var idOrder: String,
|
||||
|
||||
@SerializedName("servicio_enc_id")
|
||||
var idRequest: String,
|
||||
|
||||
@SerializedName("fecha_fin_celular")
|
||||
var endDate: String,
|
||||
|
||||
@SerializedName("lat_fin")
|
||||
var endLat: String,
|
||||
|
||||
@SerializedName("lng_fin")
|
||||
var endLng: String,
|
||||
|
||||
@SerializedName("duracion")
|
||||
var elapsedTime: String,
|
||||
|
||||
@SerializedName("comentarios")
|
||||
var comments: String,
|
||||
|
||||
@SerializedName("aplica_garantia")
|
||||
var warranty: Int,
|
||||
|
||||
@SerializedName("litraje")
|
||||
var liters: Int,
|
||||
|
||||
@SerializedName("cat_motivos_estatus_id")
|
||||
var negativeService: Int,
|
||||
|
||||
@Nullable
|
||||
@SerializedName("encuesta")
|
||||
var survey: List<Any>?,
|
||||
|
||||
@SerializedName("recibo")
|
||||
var receipt: String,
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class GenericResponse (
|
||||
@SerializedName("result")
|
||||
internal var response: String
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class KeyValue (
|
||||
@SerializedName("llave")
|
||||
var key: String,
|
||||
|
||||
@SerializedName("valor")
|
||||
var value: String
|
||||
){
|
||||
override fun toString(): String {
|
||||
return "KeyValue{" +
|
||||
"key='" + key + '\'' +
|
||||
", value='" + value + '\'' +
|
||||
'}'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.iesoluciones.siodrenax.entities.User
|
||||
|
||||
data class LoginResponse (
|
||||
@SerializedName("user")
|
||||
internal var user: User,
|
||||
|
||||
@SerializedName("token")
|
||||
internal var token: String,
|
||||
|
||||
@SerializedName("parametros")
|
||||
internal var parmams: List<KeyValue>,
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return "LoginResponse{" +
|
||||
"user=" + user +
|
||||
", token='" + token + '\'' +
|
||||
", parmams=" + parmams +
|
||||
'}'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class OpenAnswer (
|
||||
@SerializedName("pregunta_id")
|
||||
var questionId: String,
|
||||
|
||||
@SerializedName("respuesta")
|
||||
var answer: String?
|
||||
)
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
data class OrderPdf(
|
||||
var requestId: Long,
|
||||
var client: String,
|
||||
var date: String,
|
||||
var address: String,
|
||||
var city: String,
|
||||
var cellphone: String,
|
||||
var contactName: String,
|
||||
var service: String,
|
||||
var observations: String,
|
||||
var warrantyApplied: String,
|
||||
var cost: String,
|
||||
var negativeCost: String,
|
||||
var startTime: String,
|
||||
var elapsedTime: String,
|
||||
var finishTime: String,
|
||||
var advisor: String,
|
||||
var branchOffice: String,
|
||||
var sign: String,
|
||||
var auxiliar: String,
|
||||
var vehicle: String,
|
||||
var evidences: MutableMap<String, ArrayList<String>>
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
abstract class Question {
|
||||
abstract fun getId(): Long
|
||||
abstract fun getTitle(): String
|
||||
abstract fun getOrder(): Int
|
||||
abstract fun getShowNumber(): Int
|
||||
abstract fun getRequired(): Boolean
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.iesoluciones.siodrenax.entities.BusinessQuestion
|
||||
import com.iesoluciones.siodrenax.entities.DomesticQuestion
|
||||
|
||||
data class QuestionPOJO(
|
||||
@SerializedName("id")
|
||||
var id: Long,
|
||||
|
||||
@SerializedName("nombre")
|
||||
var title: String,
|
||||
|
||||
@SerializedName("orden")
|
||||
var order: Int,
|
||||
|
||||
@SerializedName("mostrar_numero")
|
||||
var showNumber: Int,
|
||||
|
||||
@SerializedName("obligatorio")
|
||||
var required: Int,
|
||||
|
||||
@SerializedName("respuestas")
|
||||
var answers: List<AnswerPOJO>
|
||||
){
|
||||
fun getDomesticQuestion(): DomesticQuestion {
|
||||
return DomesticQuestion(id, title, order, showNumber, (required == 1))
|
||||
}
|
||||
|
||||
fun getBusinessQuestion(): BusinessQuestion {
|
||||
return BusinessQuestion(id, title, order, showNumber, (required == 1))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
abstract class Reason {
|
||||
abstract fun getId(): Long
|
||||
abstract fun getTitle(): String
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.iesoluciones.siodrenax.entities.BusinessQuestion
|
||||
import com.iesoluciones.siodrenax.entities.DomesticQuestion
|
||||
import com.iesoluciones.siodrenax.entities.NegativeServiceReason
|
||||
import com.iesoluciones.siodrenax.entities.Order
|
||||
import java.util.*
|
||||
|
||||
data class StartWorkdayResponse(
|
||||
|
||||
@SerializedName("servicios")
|
||||
var orders: List<Order>,
|
||||
|
||||
@SerializedName("parametros")
|
||||
var keyValues: List<KeyValue>,
|
||||
|
||||
@SerializedName("jornada")
|
||||
var workdayInfo: Workday,
|
||||
|
||||
@SerializedName("encuesta_domestico")
|
||||
var domesticSurvey: List<QuestionPOJO>,
|
||||
|
||||
@SerializedName("encuesta_empresarial")
|
||||
var businessSurvey: List<QuestionPOJO>,
|
||||
|
||||
@SerializedName("motivos_estatus")
|
||||
var negativeServiceReason: List<NegativeServiceReason>
|
||||
){
|
||||
fun parseDomesticSurvey(): List<DomesticQuestion> {
|
||||
val survey: MutableList<DomesticQuestion> = ArrayList<DomesticQuestion>()
|
||||
for (q in domesticSurvey) {
|
||||
val question: DomesticQuestion = q.getDomesticQuestion()
|
||||
survey.add(question)
|
||||
}
|
||||
return survey
|
||||
}
|
||||
|
||||
fun parseBussinesSurvey(): List<BusinessQuestion> {
|
||||
val survey: MutableList<BusinessQuestion> = ArrayList<BusinessQuestion>()
|
||||
for (q in businessSurvey) {
|
||||
val question: BusinessQuestion = q.getBusinessQuestion()
|
||||
survey.add(question)
|
||||
}
|
||||
return survey
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
data class ValidationOrderAnswer(
|
||||
var servicio_id: String
|
||||
)
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class VehicleIncidenceResponse (
|
||||
@SerializedName("id")
|
||||
var id: Int,
|
||||
|
||||
@SerializedName("descripcion")
|
||||
var description: String
|
||||
){
|
||||
override fun toString(): String{
|
||||
return "Incidence {" +
|
||||
"id =" + id +
|
||||
", descripcion = " + description +
|
||||
'}'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.iesoluciones.siodrenax.models
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class Workday (
|
||||
@SerializedName("kilometraje_inicial")
|
||||
var startOdometer: String,
|
||||
|
||||
@SerializedName("lat_ini")
|
||||
var initLat: String,
|
||||
|
||||
@SerializedName("lng_ini")
|
||||
var initLng: String,
|
||||
|
||||
@SerializedName("vehiculo_id")
|
||||
var idVehicle: Long,
|
||||
|
||||
@SerializedName("usuario_id")
|
||||
var idUser: Long,
|
||||
|
||||
@SerializedName("fecha_hora_ini")
|
||||
var initDate: String,
|
||||
|
||||
@SerializedName("id")
|
||||
var idWorkload: Long,
|
||||
)
|
||||
118
app/src/main/java/com/iesoluciones/siodrenax/network/Api.kt
Normal file
118
app/src/main/java/com/iesoluciones/siodrenax/network/Api.kt
Normal file
@@ -0,0 +1,118 @@
|
||||
package com.iesoluciones.siodrenax.network
|
||||
|
||||
import com.iesoluciones.siodrenax.entities.*
|
||||
import com.iesoluciones.siodrenax.models.*
|
||||
import io.reactivex.Observable
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.http.*
|
||||
import java.util.*
|
||||
|
||||
interface Api {
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("login")
|
||||
fun login(
|
||||
@Header("Application") appId: String,
|
||||
@Field("email") email: String,
|
||||
@Field("password") password: String,
|
||||
@Field("version_apk") version: String,
|
||||
@Field("dispositivo_id") deviceId: String
|
||||
): Observable<LoginResponse>
|
||||
|
||||
@GET("operador/checklist")
|
||||
fun getCheckList(
|
||||
@Query("cambiar_vehiculo") changeVehicle: Int
|
||||
): Observable<List<CheckListQuestion>>
|
||||
|
||||
@GET("operador/checklist/vehiculos")
|
||||
fun getVehicle(): Observable<List<Vehicle>>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("operador/vehiculos_incidencias")
|
||||
fun sendVehicleIncidence(
|
||||
@Field("descripcion") incidence: String?
|
||||
): Observable<GenericResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("operador/vehiculos_incidencias/ultima_incidencia")
|
||||
fun getVehicleIncidence(
|
||||
@Field("vehiculo_id") vehicleId: Long
|
||||
): Observable<VehicleIncidenceResponse>
|
||||
|
||||
@PUT("operador/vehiculos_incidencias/{incidencia_id}/resolver")
|
||||
fun resolveVehicleIncidence(
|
||||
@Path("incidencia_id") incidenceId: String
|
||||
): Observable<GenericResponse>
|
||||
|
||||
@POST("operador/checklist")
|
||||
fun sendCheckList(
|
||||
@Body checkListQuestions: List<CheckListQuestion>
|
||||
): Observable<ResponseBody>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("operador/iniciarjornada")
|
||||
fun startWorkday(
|
||||
@Field("token_firebase") firebaseToken: String,
|
||||
@Field("kilometraje_inicial") odometer: String,
|
||||
@Field("lat_ini") initLat: String,
|
||||
@Field("lng_ini") initLng: String,
|
||||
@Field("modelo_celular") phoneModel: String,
|
||||
@Field("bateria") batteryLevel: String
|
||||
): Observable<StartWorkdayResponse>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("operador/finalizarjornada/{bitacora_id}")
|
||||
fun endWorkday(
|
||||
@Path("bitacora_id") idWorkday: String,
|
||||
@Field("kilometraje_final") odometer: String,
|
||||
@Field("lat_fin") lastLat: String,
|
||||
@Field("lng_fin") lastLng: String,
|
||||
@Field("modelo_celular") phoneModel: String,
|
||||
@Field("bateria") batteryLevel: String
|
||||
): Observable<ResponseBody>
|
||||
|
||||
@GET("operador/solicitud_servicios")
|
||||
fun getOrders(): Observable<List<Order>>
|
||||
|
||||
@GET("operador/solicitud_servicios/{idOrder}")
|
||||
fun getOrderInfo(
|
||||
@Path("idOrder") idWorkday: String
|
||||
): Observable<Order>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("operador/solicitud_servicios/iniciar")
|
||||
fun startOrder(
|
||||
@Field("servicio_det_id") idOrder: String,
|
||||
@Field("servicio_enc_id") idRequest: String,
|
||||
@Field("fecha_ini_celular") startDate: String,
|
||||
@Field("lat_ini") startLat: String,
|
||||
@Field("lng_ini") startLng: String
|
||||
): Observable<ResponseBody>
|
||||
|
||||
@POST("operador/solicitud_servicios/verificar/servicios")
|
||||
fun verificarServicio(@Body servicios_id: ArrayList<Long>): Observable<List<ValidationOrderAnswer>>
|
||||
|
||||
@POST("operador/solicitud_servicios/finalizar-new")
|
||||
fun finishOrder(
|
||||
@Body finishOrderRequest: FinishOrderRequest,
|
||||
): Observable<ResponseBody>
|
||||
|
||||
@GET("supervisoroperaciones/asesores")
|
||||
fun listOperators(): Observable<List<Operator>>
|
||||
|
||||
@GET("supervisoroperaciones/asesores/{asesor_id}/servicios")
|
||||
fun getOperatorOrders(
|
||||
@Path("asesor_id") idOperator: String
|
||||
): Observable<List<Order>>
|
||||
|
||||
@POST("supervisoroperaciones/iniciarjornada")
|
||||
fun startWorkdayManager(): Observable<Workday>
|
||||
|
||||
@POST("supervisoroperaciones/finalizarjornada/{bitacora_id}")
|
||||
fun endWorkdayManager(
|
||||
@Path("bitacora_id") workdayId: String
|
||||
): Observable<ResponseBody>
|
||||
|
||||
@GET("operador/servicios/diasiguiente")
|
||||
fun getNextDayOrders(): Observable<List<NextDayOrder>>
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.iesoluciones.siodrenax.network
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
internal class HttpError(json: String) {
|
||||
|
||||
@SerializedName("error")
|
||||
var error: String? = null
|
||||
|
||||
init {
|
||||
val gson = Gson()
|
||||
val temp = gson.fromJson(json, HttpError::class.java)
|
||||
error = temp.error
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun parseException(exception: HttpException): HttpError? {
|
||||
return try {
|
||||
HttpError(exception.response().errorBody()!!.source().readUtf8())
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "{error : $error}"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package com.iesoluciones.siodrenax.network
|
||||
|
||||
import com.iesoluciones.siodrenax.App
|
||||
import com.iesoluciones.siodrenax.BuildConfig.BASE_URL
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.preferencesHelper
|
||||
import com.iesoluciones.siodrenax.userBox
|
||||
import okhttp3.*
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import okio.Buffer
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class TokenInterceptor : Interceptor {
|
||||
|
||||
private var client: OkHttpClient? = null
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val original = chain.request()
|
||||
val builder = original.newBuilder()
|
||||
.addHeader("Content-Type", "application/json")
|
||||
.addHeader("Accept", "application/json")
|
||||
.addHeader("Authorization", "Bearer " + preferencesHelper.tokenApi)
|
||||
|
||||
val request = builder.build()
|
||||
val response: Response = chain.proceed(request)
|
||||
|
||||
//Instantiate Logging interceptor
|
||||
val logging = HttpLoggingInterceptor()
|
||||
logging.level = HttpLoggingInterceptor.Level.BODY
|
||||
|
||||
//Let's finish last workday started before starting a new one
|
||||
//Instantiate Http client to use
|
||||
client = OkHttpClient.Builder()
|
||||
.addInterceptor(TokenInterceptor())
|
||||
.addInterceptor(logging)
|
||||
.connectTimeout(60, TimeUnit.SECONDS)
|
||||
.readTimeout(60, TimeUnit.SECONDS)
|
||||
.writeTimeout(60, TimeUnit.SECONDS)
|
||||
.build()
|
||||
|
||||
when (response.code()) {
|
||||
401 -> {
|
||||
val body1 = response.body()!!.source().readUtf8()
|
||||
val error = HttpError(body1)
|
||||
|
||||
if (error.error != null) {
|
||||
if (error.error.toString().equals(
|
||||
App.shareInstance!!.resources.getString(R.string.token_expired),
|
||||
true
|
||||
)
|
||||
) {
|
||||
val request1 = Request.Builder()
|
||||
.url(BASE_URL + "refresh")
|
||||
.build()
|
||||
val response1 = client!!.newCall(request1).execute()
|
||||
try {
|
||||
val json = JSONObject(response1.body()!!.source().readUtf8())
|
||||
preferencesHelper.tokenApi = json.getString("token")
|
||||
val original1 = chain.request()
|
||||
val builder1 = original1.newBuilder()
|
||||
val request2 = builder1.build()
|
||||
return client!!.newCall(request2).execute()
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
} else
|
||||
return response.newBuilder()
|
||||
.body(ResponseBody.create(response.body()!!.contentType(), body1))
|
||||
.code(401).build()
|
||||
} else
|
||||
return response.newBuilder()
|
||||
.body(ResponseBody.create(response.body()!!.contentType(), body1))
|
||||
.code(401).build()
|
||||
}
|
||||
420 -> {
|
||||
val body1 = response.body()!!.source().readUtf8()
|
||||
|
||||
return response.newBuilder()
|
||||
.body(ResponseBody.create(response.body()!!.contentType(), body1))
|
||||
.code(420).build()
|
||||
}
|
||||
422 -> {
|
||||
val body1 = response.body()!!.source().readUtf8()
|
||||
val error1 = UnprocessableEntity(body1)
|
||||
|
||||
if (error1.message.contentEquals(App.shareInstance!!.resources.getString(R.string.workday_already_started))) {
|
||||
|
||||
//Extract the request body, the same data of the body will be used to finish pending workday
|
||||
var requestBody = request.body()
|
||||
|
||||
//Modify some keys to match the one requested by the web service
|
||||
requestBody = processFormDataRequestBody(requestBody!!)
|
||||
val response1: Response
|
||||
|
||||
if (userBox.query().build().findUnique()!!.idEmployeeType == 2L) {
|
||||
//Set up request
|
||||
val request1 = Request.Builder()
|
||||
.url(
|
||||
BASE_URL + "operador/finalizarjornada/" + error1.errors[0]
|
||||
) //concatenate id of last workday
|
||||
.post(requestBody!!)
|
||||
.build()
|
||||
//Call response
|
||||
response1 = client!!.newCall(request1).execute()
|
||||
} else {
|
||||
//Set up request
|
||||
val request1 = Request.Builder()
|
||||
.url(
|
||||
BASE_URL + "supervisoroperaciones/finalizarjornada/" + error1.errors[0]
|
||||
) //concatenate id of last workday
|
||||
.post(requestBody!!)
|
||||
.build()
|
||||
//Call response
|
||||
response1 = client!!.newCall(request1).execute()
|
||||
}
|
||||
|
||||
//Validate succesful workday finish
|
||||
return if (response1.code() == 200) {
|
||||
//try again startworkday
|
||||
client!!.newCall(chain.request()).execute()
|
||||
} else {
|
||||
//There was something wrong with the process , just pass the error to main Thread
|
||||
val body = response1.body()!!.source().readUtf8()
|
||||
response.newBuilder()
|
||||
.body(ResponseBody.create(response.body()!!.contentType(), body))
|
||||
.code(422).build()
|
||||
}
|
||||
|
||||
} else {
|
||||
return response.newBuilder()
|
||||
.body(ResponseBody.create(response.body()!!.contentType(), body1))
|
||||
.code(422).build()
|
||||
}
|
||||
}
|
||||
else -> return response
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
private fun bodyToString(request: RequestBody?): String {
|
||||
try {
|
||||
val buffer = Buffer()
|
||||
if (request != null)
|
||||
request.writeTo(buffer)
|
||||
else
|
||||
return ""
|
||||
return buffer.readUtf8()
|
||||
} catch (e: IOException) {
|
||||
return "did not work"
|
||||
}
|
||||
}
|
||||
|
||||
private fun processFormDataRequestBody(requestBody: RequestBody): RequestBody? {
|
||||
val formBody: RequestBody = FormBody.Builder().build()
|
||||
var postBodyString = bodyToString(requestBody)
|
||||
postBodyString += (if (postBodyString.isNotEmpty()) "&" else "") + bodyToString(formBody)
|
||||
postBodyString = postBodyString.replace("kilometraje_inicial", "kilometraje_final")
|
||||
postBodyString = postBodyString.replace("lat_ini", "lat_fin")
|
||||
postBodyString = postBodyString.replace("lng_ini", "lng_fin")
|
||||
return RequestBody.create(requestBody.contentType(), postBodyString)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.iesoluciones.siodrenax.network
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
class UnprocessableEntity(json: String) {
|
||||
|
||||
@SerializedName("message")
|
||||
var message: String
|
||||
internal set
|
||||
@SerializedName("errors")
|
||||
var errors: List<String>
|
||||
internal set
|
||||
|
||||
init {
|
||||
val gson = Gson()
|
||||
val temp = gson.fromJson(json, UnprocessableEntity::class.java)
|
||||
message = temp.message
|
||||
errors = temp.errors
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun parseException(exception: HttpException): UnprocessableEntity? {
|
||||
return try {
|
||||
UnprocessableEntity(exception.response().errorBody()!!.source().readUtf8().toString())
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "UnprocessableEntity{" +
|
||||
"message='" + message + '\''.toString() +
|
||||
", errors=" + errors +
|
||||
'}'.toString()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.iesoluciones.siodrenax.receivers
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import com.iesoluciones.siodrenax.services.NotificationService.Companion.UPDATE_UI
|
||||
|
||||
class UpdateUIReceiver: BroadcastReceiver() {
|
||||
|
||||
private var listener: UiUpdateListener? = null
|
||||
|
||||
interface UiUpdateListener {
|
||||
fun updateUI()
|
||||
}
|
||||
|
||||
fun updateUIReceiver(listener: UiUpdateListener) {
|
||||
this.listener = listener
|
||||
(listener as Context).registerReceiver(this, IntentFilter(UPDATE_UI))
|
||||
}
|
||||
|
||||
fun unRegisterReceiver(listener: UiUpdateListener) {
|
||||
(listener as Context).unregisterReceiver(this)
|
||||
}
|
||||
|
||||
fun registerReceiver(listener: UiUpdateListener) {
|
||||
this.listener = listener
|
||||
(listener as Context).registerReceiver(this, IntentFilter(UPDATE_UI))
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
if (listener != null) listener!!.updateUI()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.iesoluciones.siodrenax.repositories
|
||||
|
||||
import com.iesoluciones.siodrenax.api
|
||||
import com.iesoluciones.siodrenax.checkListQuestionBox
|
||||
import com.iesoluciones.siodrenax.entities.CheckListQuestion
|
||||
import com.iesoluciones.siodrenax.entities.CheckListQuestion_
|
||||
import com.iesoluciones.siodrenax.utils.Constants
|
||||
import io.objectbox.kotlin.and
|
||||
import io.objectbox.kotlin.equal
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.observers.ResourceObserver
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
|
||||
class CheckListRepository {
|
||||
|
||||
interface CheckListInterface {
|
||||
fun success()
|
||||
fun failure(throwable: Throwable)
|
||||
}
|
||||
|
||||
fun isCheckListDone(): Boolean {
|
||||
return checkListQuestionBox.query()
|
||||
.build()
|
||||
.find().isNotEmpty()
|
||||
}
|
||||
|
||||
fun getSurveyCheckList(tipo: String): List<CheckListQuestion> {
|
||||
|
||||
return checkListQuestionBox.query(
|
||||
CheckListQuestion_.tipo equal tipo
|
||||
)
|
||||
.build()
|
||||
.find()
|
||||
}
|
||||
|
||||
fun isValidRevision(): Boolean {
|
||||
val totalRadio = checkListQuestionBox.query(
|
||||
CheckListQuestion_.tipo equal Constants.REVISION
|
||||
and (CheckListQuestion_.tipoRadioBtn equal 1)
|
||||
and (CheckListQuestion_.respuestaRadioBtn.isNull)
|
||||
)
|
||||
.build()
|
||||
.count()
|
||||
|
||||
val totalSelect = checkListQuestionBox.query(
|
||||
CheckListQuestion_.tipo equal Constants.REVISION
|
||||
and (CheckListQuestion_.tipoCheckBox equal 0)
|
||||
and (CheckListQuestion_.tipoRadioBtn equal 0)
|
||||
and (CheckListQuestion_.tipoText equal 0)
|
||||
and (CheckListQuestion_.respuestaText.isNull)
|
||||
)
|
||||
.build()
|
||||
.count()
|
||||
|
||||
return (totalRadio + totalSelect) == 0L
|
||||
}
|
||||
|
||||
fun finalizarEncuesta(checkListInterface: CheckListInterface) {
|
||||
|
||||
api.sendCheckList(checkListQuestionBox.all)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { response ->
|
||||
checkListQuestionBox.removeAll()
|
||||
response
|
||||
}
|
||||
.subscribe(object : ResourceObserver<ResponseBody>() {
|
||||
override fun onNext(responseBody: ResponseBody) {}
|
||||
|
||||
override fun onError(e: Throwable) = checkListInterface.failure(e)
|
||||
|
||||
override fun onComplete() = checkListInterface.success()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.iesoluciones.siodrenax.repositories
|
||||
|
||||
import com.iesoluciones.siodrenax.entities.Evidence
|
||||
import com.iesoluciones.siodrenax.evidenceBox
|
||||
|
||||
class EvidenceRepository {
|
||||
|
||||
fun getEvidenceById(idEvidence: Long): Evidence {
|
||||
return evidenceBox.get(idEvidence)
|
||||
}
|
||||
|
||||
fun saveEvidence(evidence: Evidence) {
|
||||
evidenceBox.put(evidence)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.iesoluciones.siodrenax.repositories
|
||||
|
||||
import com.iesoluciones.siodrenax.api
|
||||
import com.iesoluciones.siodrenax.models.GenericResponse
|
||||
import com.iesoluciones.siodrenax.models.VehicleIncidenceResponse
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.observers.ResourceObserver
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
class IncidenceRepository {
|
||||
|
||||
interface IncidenceInterface {
|
||||
fun success(genericResponse: String?)
|
||||
fun failure(throwable: Throwable)
|
||||
}
|
||||
|
||||
interface GetIncidenceInterface {
|
||||
fun success(response: VehicleIncidenceResponse?)
|
||||
fun failure(throwable: Throwable)
|
||||
}
|
||||
|
||||
fun sendVehicleIncidenceRequest(incidence: String, incidenceInterface: IncidenceInterface) {
|
||||
|
||||
api.sendVehicleIncidence(incidence)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { response ->
|
||||
response
|
||||
}
|
||||
.subscribe(object : ResourceObserver<GenericResponse>() {
|
||||
override fun onNext(s: GenericResponse) {
|
||||
incidenceInterface.success(s.response)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
incidenceInterface.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun getVehicleIncidenceRequest(vehicleId: Long, incidenceInterface: GetIncidenceInterface) {
|
||||
|
||||
api.getVehicleIncidence(vehicleId)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { response ->
|
||||
response
|
||||
}
|
||||
.subscribe(object : ResourceObserver<VehicleIncidenceResponse>() {
|
||||
override fun onNext(s: VehicleIncidenceResponse) {
|
||||
incidenceInterface.success(s)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
incidenceInterface.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun resolveVehicleIncidenceRequest(incidenceId: String, incidenceInterface: IncidenceInterface) {
|
||||
|
||||
api.resolveVehicleIncidence(incidenceId)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { response ->
|
||||
response
|
||||
}
|
||||
.subscribe(object : ResourceObserver<GenericResponse>() {
|
||||
override fun onNext(s: GenericResponse) {
|
||||
incidenceInterface.success(s.response)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
incidenceInterface.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.iesoluciones.siodrenax.repositories
|
||||
|
||||
import com.iesoluciones.siodrenax.*
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.APP_ID
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.EMPLOYEE_MANAGER
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.observers.ResourceObserver
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
class LoginRepository {
|
||||
|
||||
interface LoginInterface {
|
||||
fun success(result: Boolean)
|
||||
fun failure(throwable: Throwable)
|
||||
}
|
||||
|
||||
fun loginRequest(username: String, password: String, deviceId: String, loginInterface: LoginInterface) {
|
||||
|
||||
val obLogin = api.login(APP_ID, username, password, BuildConfig.VERSION_NAME, deviceId)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { response ->
|
||||
preferencesHelper.tokenApi = response.token
|
||||
val user = response.user
|
||||
userBox.put(user)
|
||||
preferencesHelper.isManager = user.idEmployeeType == EMPLOYEE_MANAGER
|
||||
response
|
||||
}
|
||||
|
||||
val obCheckList = api.getCheckList(0)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { response ->
|
||||
checkListQuestionBox.put(response)
|
||||
response
|
||||
}
|
||||
|
||||
val obVehicle = api.getVehicle()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { response ->
|
||||
vehicleBox.put(response)
|
||||
response
|
||||
}
|
||||
|
||||
Observable.concat(obLogin, obCheckList, obVehicle)
|
||||
.subscribe(object : ResourceObserver<Any?>() {
|
||||
override fun onNext(t: Any) {
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
loginInterface.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
loginInterface.success(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.iesoluciones.siodrenax.repositories
|
||||
|
||||
import com.iesoluciones.siodrenax.api
|
||||
import com.iesoluciones.siodrenax.entities.Operator
|
||||
import com.iesoluciones.siodrenax.entities.Order
|
||||
import com.iesoluciones.siodrenax.entities.User
|
||||
import com.iesoluciones.siodrenax.models.Workday
|
||||
import com.iesoluciones.siodrenax.operatorBox
|
||||
import com.iesoluciones.siodrenax.preferencesHelper
|
||||
import com.iesoluciones.siodrenax.userBox
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.observers.ResourceObserver
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
|
||||
class ManagerRepository {
|
||||
|
||||
interface OnOrdersRetrievedListener {
|
||||
fun success(orders: List<Order>)
|
||||
fun failure(throwable: Throwable)
|
||||
}
|
||||
|
||||
interface OnOperatorsRetrievedListener {
|
||||
fun success(operators: List<Operator>)
|
||||
fun failure(throwable: Throwable)
|
||||
}
|
||||
|
||||
interface OnWebServiceCalled {
|
||||
fun success()
|
||||
fun failure(e: Throwable)
|
||||
}
|
||||
|
||||
fun getOperatorList(listener: OnOperatorsRetrievedListener){
|
||||
api.listOperators()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.subscribe(object : ResourceObserver<List<Operator>>() {
|
||||
override fun onNext(operators: List<Operator>) {
|
||||
operatorBox.put(operators)
|
||||
listener.success(operators)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
listener.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {}
|
||||
})
|
||||
}
|
||||
|
||||
fun getOperatorOrders(idOperator: String, listener: OnOrdersRetrievedListener){
|
||||
api.getOperatorOrders(idOperator)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.subscribe(object : ResourceObserver<List<Order>>() {
|
||||
override fun onNext(orders: List<Order>) {
|
||||
listener.success(orders)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
listener.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {}
|
||||
})
|
||||
}
|
||||
|
||||
fun getOperatorsFromDb(): List<Operator> {
|
||||
return operatorBox.all
|
||||
}
|
||||
|
||||
fun logOut(){
|
||||
operatorBox.removeAll()
|
||||
userBox.removeAll()
|
||||
preferencesHelper.tokenApi = null
|
||||
preferencesHelper.tokenFirebase = null
|
||||
preferencesHelper.isManager = false
|
||||
preferencesHelper.workdayStarted = false
|
||||
preferencesHelper.workdayId = 0
|
||||
}
|
||||
|
||||
fun startWorkday(listener: OnWebServiceCalled){
|
||||
api.startWorkdayManager()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.subscribe(object : ResourceObserver<Workday>() {
|
||||
override fun onNext(workday: Workday) {
|
||||
preferencesHelper.workdayId = workday.idWorkload.toInt()
|
||||
listener.success()
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
listener.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {}
|
||||
})
|
||||
}
|
||||
|
||||
fun endWorkday(listener: OnWebServiceCalled){
|
||||
api.endWorkdayManager(preferencesHelper.workdayId.toString())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.subscribe(object : ResourceObserver<ResponseBody>() {
|
||||
override fun onNext(responseBody: ResponseBody) {
|
||||
logOut()
|
||||
listener.success()
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
listener.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {}
|
||||
})
|
||||
}
|
||||
|
||||
fun getUserData(): User {
|
||||
return userBox.all[0]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
package com.iesoluciones.siodrenax.repositories
|
||||
|
||||
import android.content.Intent
|
||||
import com.iesoluciones.siodrenax.*
|
||||
import com.iesoluciones.siodrenax.App.Companion.shareInstance
|
||||
import com.iesoluciones.siodrenax.entities.*
|
||||
import com.iesoluciones.siodrenax.models.EvidenceRequest
|
||||
import com.iesoluciones.siodrenax.models.FinishOrderRequest
|
||||
import com.iesoluciones.siodrenax.models.Question
|
||||
import com.iesoluciones.siodrenax.models.ValidationOrderAnswer
|
||||
import com.iesoluciones.siodrenax.services.NotificationService
|
||||
import com.iesoluciones.siodrenax.utils.Constants
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import io.objectbox.kotlin.equal
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.observers.ResourceObserver
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
|
||||
|
||||
class OrdersRepository {
|
||||
|
||||
interface OnRefreshOrders {
|
||||
fun success(orders: List<Order>)
|
||||
fun failure(throwable: Throwable)
|
||||
}
|
||||
|
||||
interface OnRefreshONextDayOrders {
|
||||
fun success(nextDayOrders: List<NextDayOrder>)
|
||||
fun failure(throwable: Throwable)
|
||||
}
|
||||
|
||||
interface OnOrderRequestAnswered {
|
||||
fun success(orderResponse: ResponseBody)
|
||||
fun failure(throwable: Throwable)
|
||||
}
|
||||
|
||||
fun getOrders(): List<Order> {
|
||||
return orderBox.query()
|
||||
.order(Order_.dateServiceRequest)
|
||||
.build()
|
||||
.find()
|
||||
}
|
||||
|
||||
fun getOrderById(id: Long): Order? {
|
||||
return orderBox.query()
|
||||
.equal(Order_.id, id)
|
||||
.build()
|
||||
.findFirst()
|
||||
}
|
||||
|
||||
fun getOrderByIdRequest(idRequest: Long): Order? {
|
||||
return orderBox.query()
|
||||
.equal(Order_.idRequest, idRequest)
|
||||
.build()
|
||||
.findFirst()
|
||||
}
|
||||
|
||||
fun getOrderProgressById(id: Long): OrderProgress? {
|
||||
return orderProgressBox.query()
|
||||
.equal(OrderProgress_.id, id)
|
||||
.build()
|
||||
.findFirst()
|
||||
}
|
||||
|
||||
fun refreshOrders(listener: OnRefreshOrders, filesDir: String) {
|
||||
|
||||
api.getOrders()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.subscribe(object : ResourceObserver<List<Order>>() {
|
||||
override fun onNext(orders: List<Order>) {
|
||||
|
||||
val ordersInBox: List<Order> =
|
||||
orderBox.query().order(Order_.dateServiceRequest).build().find()
|
||||
for (o in ordersInBox) {
|
||||
val orderProgress: OrderProgress? = getOrderProgressById(o.id)
|
||||
if (orderProgress == null || orderProgress.isSent) {
|
||||
orderBox.remove(o.id)
|
||||
}
|
||||
}
|
||||
orderBox.put(orders)
|
||||
HelperUtil().downloadSketchs(filesDir,orders)
|
||||
listener.success(getOrders())
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
listener.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {}
|
||||
})
|
||||
}
|
||||
|
||||
fun startOrder(
|
||||
idOrder: String,
|
||||
idRequest: String,
|
||||
startDate: String,
|
||||
startLat: String,
|
||||
startLng: String,
|
||||
listener: OnOrderRequestAnswered
|
||||
) {
|
||||
api.startOrder(idOrder, idRequest, startDate, startLat, startLng)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.subscribe(object : ResourceObserver<ResponseBody>() {
|
||||
override fun onNext(responseBody: ResponseBody) {
|
||||
HelperUtil().createEvidences(getOrderById(idOrder.toLong())!!)
|
||||
val orderProgress = OrderProgress()
|
||||
orderProgress.id = idOrder.toLong()
|
||||
orderProgress.idRequest = idRequest.toLong()
|
||||
orderProgress.startDate = startDate
|
||||
orderProgress.startLat = startLat
|
||||
orderProgress.startLng = startLng
|
||||
|
||||
orderProgressBox.put(orderProgress)
|
||||
preferencesHelper.orderInProgress = idOrder.toLong()
|
||||
listener.success(responseBody)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
listener.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {}
|
||||
})
|
||||
}
|
||||
|
||||
fun createSurveyAnswerHolders(order: Order) {
|
||||
val surveyRepository = SurveyRepository()
|
||||
|
||||
val questions: List<Question> =
|
||||
if (order.idServiceType == Constants.ID_SERVICE_TYPE_DOMESTIC) {
|
||||
surveyRepository.getSurveyQuestions(true)
|
||||
} else {
|
||||
surveyRepository.getSurveyQuestions(false)
|
||||
}
|
||||
|
||||
for (q in questions) {
|
||||
val savedAnswer = SavedAnswer()
|
||||
savedAnswer.orderId = order.id
|
||||
savedAnswer.questionId = q.getId()
|
||||
|
||||
savedAnswerBox.put(savedAnswer)
|
||||
}
|
||||
}
|
||||
|
||||
fun getEvidences(idOrder: Long): List<Evidence> {
|
||||
return evidenceBox.query()
|
||||
.equal(Evidence_.idOrder, idOrder)
|
||||
.order(Evidence_.id)
|
||||
.build()
|
||||
.find(0, 9)
|
||||
}
|
||||
|
||||
fun getEvidencesForZip(idOrder: Long): List<Evidence> {
|
||||
return evidenceBox.query()
|
||||
.equal(Evidence_.idOrder, idOrder)
|
||||
.and()
|
||||
.notNull(Evidence_.path)
|
||||
.build()
|
||||
.find()
|
||||
}
|
||||
|
||||
fun getEvidencesForPdf(idOrder: Long): List<Evidence> {
|
||||
return evidenceBox.query()
|
||||
.equal(Evidence_.idOrder, idOrder)
|
||||
.and()
|
||||
.notNull(Evidence_.path)
|
||||
.order(Evidence_.evidenceNo)
|
||||
.build()
|
||||
.find()
|
||||
}
|
||||
|
||||
fun saveOrderProgress(orderProgress: OrderProgress) {
|
||||
orderProgressBox.put(orderProgress)
|
||||
}
|
||||
|
||||
fun getPendingOrders(): List<OrderProgress> {
|
||||
//System.gc()
|
||||
|
||||
val ordersIdList = orderProgressBox.query()
|
||||
.equal(OrderProgress_.shouldBeSent, true)
|
||||
.and().equal(OrderProgress_.isSent, false)
|
||||
.build()
|
||||
.findIds()
|
||||
|
||||
validateOrdersSuccess(ordersIdList.toCollection(ArrayList()))
|
||||
|
||||
return orderProgressBox.query()
|
||||
.equal(OrderProgress_.shouldBeSent, true)
|
||||
.and().equal(OrderProgress_.isSent, false)
|
||||
.build()
|
||||
.find()
|
||||
}
|
||||
|
||||
private fun validateOrdersSuccess(ordersIdList: ArrayList<Long>) {
|
||||
api.verificarServicio(ordersIdList)
|
||||
.subscribeOn(Schedulers.trampoline())
|
||||
.observeOn(Schedulers.trampoline())
|
||||
.subscribe(object : ResourceObserver<List<ValidationOrderAnswer>>() {
|
||||
override fun onNext(validationOrderAnswers: List<ValidationOrderAnswer>) {
|
||||
for (v in validationOrderAnswers) {
|
||||
|
||||
evidenceBox.query(
|
||||
Evidence_.idOrder equal v.servicio_id
|
||||
)
|
||||
.build()
|
||||
.remove()
|
||||
|
||||
orderProgressBox.remove(v.servicio_id.toLong())
|
||||
orderBox.remove(v.servicio_id.toLong())
|
||||
|
||||
//TODO
|
||||
// shareInstance!!.sendBroadcast(Intent(PushNotificationMessagingService.UPDATE_UI))
|
||||
// shareInstance!!.startService(Intent(shareInstance, CleaningService::class.java))
|
||||
preferencesHelper.orderInProgress = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {}
|
||||
override fun onComplete() {}
|
||||
})
|
||||
}
|
||||
|
||||
private fun getPendingEvidences(idOrder: String): List<Evidence> {
|
||||
return evidenceBox.query()
|
||||
.equal(Evidence_.idOrder, idOrder.toLong())
|
||||
.and().equal(Evidence_.isSent, false)
|
||||
.and().notNull(Evidence_.path)
|
||||
.build()
|
||||
.find()
|
||||
}
|
||||
|
||||
fun prepareFinishOrder(orderProgress: OrderProgress): Observable<ResponseBody> {
|
||||
|
||||
val order = getOrderById(orderProgress.id)!!
|
||||
val answers: List<Any> = SurveyRepository().getSurveyBody(order)
|
||||
|
||||
val evidences = arrayListOf<EvidenceRequest>()
|
||||
getEvidencesForZip(orderProgress.id).forEach {
|
||||
evidences.add(EvidenceRequest(it.name!!, it.getTypeDescription(), it.lat, it.lng))
|
||||
}
|
||||
|
||||
val finishOrderRequest = FinishOrderRequest(
|
||||
idOrder = orderProgress.id.toString(),
|
||||
idRequest = orderProgress.idRequest.toString(),
|
||||
endDate = orderProgress.endDate!!,
|
||||
endLat = orderProgress.endLat,
|
||||
endLng = orderProgress.endLng,
|
||||
elapsedTime = orderProgress.elapsedTime!!,
|
||||
comments = orderProgress.comments!!,
|
||||
warranty = if (orderProgress.warranty) 1 else 0,
|
||||
liters = orderProgress.liters,
|
||||
negativeService = orderProgress.negativeService,
|
||||
survey = if (order.SurveyRequired == 1 && orderProgress.shouldSendSurvey) answers else null,
|
||||
receipt = HelperUtil().encodeBase64(order.pdfPath!!)!!
|
||||
)
|
||||
|
||||
return api.finishOrder(finishOrderRequest)
|
||||
.doOnNext {
|
||||
removeAllOrdersInformation(
|
||||
orderProgress.id,
|
||||
order.pdfPath!!,
|
||||
orderProgress.signaturePath!!
|
||||
)
|
||||
shareInstance!!.sendBroadcast(Intent(NotificationService.UPDATE_UI))
|
||||
preferencesHelper.orderInProgress = null
|
||||
}
|
||||
.doOnError {
|
||||
orderProgress.isSent = false
|
||||
orderProgressBox.put(orderProgress)
|
||||
}
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
}
|
||||
|
||||
fun validateEvidences(idOrder: String): Boolean {
|
||||
// Validar almenos una imagen de cada etapa
|
||||
/*
|
||||
val evidences = getPendingEvidences(idOrder)
|
||||
var hasAtLeastOneStartEvicende = false
|
||||
var hasAtLeastOneProcessEvicende = false
|
||||
var hasAtLeastOneFinalEvicende = false
|
||||
|
||||
for (e in evidences) {
|
||||
when (e.type) {
|
||||
Constants.EVIDENCE_START -> hasAtLeastOneStartEvicende = true
|
||||
Constants.EVIDENCE_PROCESS -> hasAtLeastOneProcessEvicende = true
|
||||
Constants.EVIDENCE_FINAL -> hasAtLeastOneFinalEvicende = true
|
||||
}
|
||||
}
|
||||
return hasAtLeastOneStartEvicende && hasAtLeastOneProcessEvicende && hasAtLeastOneFinalEvicende
|
||||
*/
|
||||
|
||||
return getPendingEvidences(idOrder).size == 9
|
||||
}
|
||||
|
||||
fun getNextDayOrders(): List<NextDayOrder> {
|
||||
return nextDayOrderBox.query()
|
||||
.order(NextDayOrder_.dateServiceRequest)
|
||||
.build()
|
||||
.find()
|
||||
}
|
||||
|
||||
fun refreshNextDayOrders(listener: OnRefreshONextDayOrders) {
|
||||
api.getNextDayOrders()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.subscribe(object : ResourceObserver<List<NextDayOrder>>() {
|
||||
override fun onNext(orders: List<NextDayOrder>) {
|
||||
nextDayOrderBox.removeAll()
|
||||
nextDayOrderBox.put(orders)
|
||||
listener.success(getNextDayOrders())
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
listener.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {}
|
||||
})
|
||||
}
|
||||
|
||||
private fun removeAllOrdersInformation(idOrder: Long, pdfPath: String, signaturePath: String) {
|
||||
|
||||
getEvidencesForZip(idOrder).forEach {
|
||||
HelperUtil().deleteFile(it.path!!)
|
||||
}
|
||||
|
||||
HelperUtil().deleteFile(pdfPath)
|
||||
HelperUtil().deleteFile(signaturePath)
|
||||
|
||||
evidenceBox.query()
|
||||
.equal(Evidence_.idOrder, idOrder)
|
||||
.build()
|
||||
.remove()
|
||||
|
||||
savedAnswerBox.query()
|
||||
.equal(SavedAnswer_.orderId, idOrder)
|
||||
.build()
|
||||
.remove()
|
||||
|
||||
orderProgressBox.remove(idOrder)
|
||||
|
||||
orderBox.remove(idOrder)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.iesoluciones.siodrenax.repositories
|
||||
|
||||
import android.util.Log
|
||||
import com.iesoluciones.siodrenax.*
|
||||
import com.iesoluciones.siodrenax.entities.*
|
||||
import com.iesoluciones.siodrenax.models.*
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.IDSERVICETYPEDOMESTIC
|
||||
import java.util.*
|
||||
|
||||
class SurveyRepository {
|
||||
|
||||
fun getSurveyQuestions(isDomestic: Boolean): List<Question> {
|
||||
val questions: MutableList<Question> = ArrayList<Question>()
|
||||
if (isDomestic) {
|
||||
questions.addAll(domesticQuestionBox.all)
|
||||
} else {
|
||||
questions.addAll(businessQuestionBox.all)
|
||||
}
|
||||
return questions
|
||||
}
|
||||
|
||||
fun getSurveyBody(order: Order): List<Any> {
|
||||
// NullPointerException launched once. The "Order" is a non null object.
|
||||
// Commented to track the error -------------> Incidents = 12
|
||||
val answerKeyValues: MutableList<Any> = ArrayList<Any>()
|
||||
val questions =
|
||||
getSurveyQuestions(order.idServiceType == IDSERVICETYPEDOMESTIC)
|
||||
for (q in questions) {
|
||||
val answer: SavedAnswer? = getSavedAnswer(q, order)
|
||||
if (answer != null) {
|
||||
if (answer.isOpen)
|
||||
answerKeyValues.add(OpenAnswer(q.getId().toString(), answer.answer))
|
||||
else
|
||||
answerKeyValues.add(CheckBoxAnswer(q.getId().toString(), answer.answer))
|
||||
}
|
||||
}
|
||||
return answerKeyValues
|
||||
}
|
||||
|
||||
fun deleteAllSavedAnswers(order: Order) {
|
||||
savedAnswerBox.query()
|
||||
.equal(SavedAnswer_.orderId, order.id)
|
||||
.build()
|
||||
.remove()
|
||||
}
|
||||
|
||||
private fun getSavedAnswer(question: Question, order: Order): SavedAnswer? {
|
||||
return savedAnswerBox.query()
|
||||
.equal(SavedAnswer_.orderId, order.id)
|
||||
.and().equal(SavedAnswer_.questionId, question.getId())
|
||||
.build()
|
||||
.findFirst()
|
||||
}
|
||||
|
||||
fun getNegativeServiceReason(): List<Reason> {
|
||||
return negativeServiceReasonBox.all
|
||||
}
|
||||
|
||||
fun validateAnswers(order: Order): Boolean {
|
||||
val questions = getSurveyQuestions(order.idServiceType == IDSERVICETYPEDOMESTIC)
|
||||
for (q in questions) {
|
||||
|
||||
val answer: String? = getQuestionSavedAnswer(q, order)
|
||||
if (q.getRequired() && (answer == null || answer.trim { it <= ' ' } == ""))
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun getQuestionSavedAnswer(question: Question, order: Order): String? {
|
||||
return getSavedAnswer(question, order)?.answer
|
||||
}
|
||||
|
||||
fun getAnswers(q: Question, isDomestic: Boolean): List<Answer> {
|
||||
return if (isDomestic) getDomesticQuestionAnswers(q) else getBusinessQuestionAnswers(q)
|
||||
}
|
||||
|
||||
private fun getDomesticQuestionAnswers(q: Question): List<Answer> {
|
||||
return domesticAnswerBox.query()
|
||||
.equal(DomesticAnswer_.idQuestion, q.getId())
|
||||
.build()
|
||||
.find()
|
||||
}
|
||||
|
||||
private fun getBusinessQuestionAnswers(q: Question): List<Answer> {
|
||||
return businessAnswerBox.query()
|
||||
.equal(BusinessAnswer_.idQuestion, q.getId())
|
||||
.build()
|
||||
.find()
|
||||
}
|
||||
|
||||
fun saveQuestionAnswer(question: Question, order: Order, answer: String?, isOpen: Boolean) {
|
||||
val savedAnswer = getSavedAnswer(question, order)
|
||||
|
||||
if (savedAnswer != null) {
|
||||
savedAnswer.isOpen = isOpen
|
||||
savedAnswer.answer = answer
|
||||
savedAnswerBox.put(savedAnswer)
|
||||
} else {
|
||||
Log.e("SurveyRepository", "Trouble trying to save answer $answer")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
package com.iesoluciones.siodrenax.repositories
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.BatteryManager
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION_CODES
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.iesoluciones.siodrenax.*
|
||||
import com.iesoluciones.siodrenax.App.Companion.context
|
||||
import com.iesoluciones.siodrenax.App.Companion.shareInstance
|
||||
import com.iesoluciones.siodrenax.entities.OrderProgress_
|
||||
import com.iesoluciones.siodrenax.entities.User
|
||||
import com.iesoluciones.siodrenax.models.StartWorkdayResponse
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.observers.ResourceObserver
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import okhttp3.ResponseBody
|
||||
|
||||
class WorkdayRepository {
|
||||
|
||||
interface WorkdayInterface {
|
||||
fun success(response: StartWorkdayResponse)
|
||||
fun failure(throwable: Throwable)
|
||||
}
|
||||
|
||||
interface WorkdayEndInterface {
|
||||
fun success(response: ResponseBody)
|
||||
fun failure(throwable: Throwable)
|
||||
}
|
||||
|
||||
fun startWorkdayRequest(
|
||||
firebaseToken: String,
|
||||
odometer: String,
|
||||
initLat: String,
|
||||
initLng: String,
|
||||
filesDir: String,
|
||||
listener: WorkdayInterface
|
||||
) {
|
||||
//obtain device model info
|
||||
val reqString = (Build.MANUFACTURER
|
||||
+ " " + Build.MODEL + " " + Build.VERSION.RELEASE
|
||||
+ " " + VERSION_CODES::class.java.fields[Build.VERSION.SDK_INT].name)
|
||||
|
||||
//Obtain device battery percentage in integer
|
||||
val ifilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
|
||||
val batteryStatus: Intent = shareInstance!!.registerReceiver(null, ifilter)!!
|
||||
val level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
|
||||
val scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
|
||||
val batteryPct = level / scale.toDouble() * 100.0
|
||||
val battery = batteryPct.toInt()
|
||||
|
||||
api.startWorkday(
|
||||
firebaseToken,
|
||||
odometer,
|
||||
initLat,
|
||||
initLng,
|
||||
reqString,
|
||||
battery.toString() + ""
|
||||
)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { response ->
|
||||
processWorkdayResponse(response, filesDir)
|
||||
response
|
||||
}
|
||||
.subscribe(object : ResourceObserver<StartWorkdayResponse>() {
|
||||
override fun onNext(response: StartWorkdayResponse) {
|
||||
listener.success(response)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
listener.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
private fun processWorkdayResponse(response: StartWorkdayResponse, filesDir: String){
|
||||
preferencesHelper.workdayStarted = true
|
||||
preferencesHelper.workdayId = response.workdayInfo.idWorkload.toInt()
|
||||
|
||||
orderBox.put(response.orders)
|
||||
domesticQuestionBox.put(response.parseDomesticSurvey())
|
||||
businessQuestionBox.put(response.parseBussinesSurvey())
|
||||
negativeServiceReasonBox.put(response.negativeServiceReason)
|
||||
|
||||
for (q in response.businessSurvey)
|
||||
for (answerPOJO in q.answers)
|
||||
businessAnswerBox.put(answerPOJO.getBusinessAnswer())
|
||||
|
||||
for (q in response.domesticSurvey)
|
||||
for (answerPOJO in q.answers)
|
||||
domesticAnswerBox.put(answerPOJO.getDomesticAnswer())
|
||||
|
||||
|
||||
for (keyValue in response.keyValues)
|
||||
if (keyValue.key == shareInstance!!.getString(R.string.gps_interval_param))
|
||||
preferencesHelper.gpsInterval = keyValue.value.toInt()
|
||||
|
||||
|
||||
HelperUtil().downloadSketchs(filesDir,response.orders)
|
||||
}
|
||||
|
||||
fun endWorkdayRequest(
|
||||
odometer: String,
|
||||
endLat: String,
|
||||
endLng: String,
|
||||
listener: WorkdayEndInterface
|
||||
){
|
||||
|
||||
val reqString = (Build.MANUFACTURER
|
||||
+ " " + Build.MODEL + " " + Build.VERSION.RELEASE
|
||||
+ " " + VERSION_CODES::class.java.fields[Build.VERSION.SDK_INT].name)
|
||||
|
||||
val ifilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
|
||||
val batteryStatus: Intent = shareInstance!!.registerReceiver(null, ifilter)!!
|
||||
val level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
|
||||
val scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
|
||||
val batteryPct = level / scale.toDouble() * 100.0
|
||||
val battery = batteryPct.toInt()
|
||||
|
||||
api.endWorkday(
|
||||
preferencesHelper.workdayId.toString(),
|
||||
odometer,
|
||||
endLat,
|
||||
endLng,
|
||||
reqString,
|
||||
battery.toString()
|
||||
)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { response ->
|
||||
preferencesHelper.workdayStarted = false
|
||||
preferencesHelper.workdayId = 0
|
||||
response
|
||||
}
|
||||
.subscribe(object : ResourceObserver<ResponseBody>() {
|
||||
override fun onNext(response: ResponseBody) {
|
||||
listener.success(response)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
listener.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun validateChangeVehicle(): Boolean {
|
||||
return orderProgressBox.query()
|
||||
.equal(OrderProgress_.isSent, false)
|
||||
.build()
|
||||
.find()
|
||||
.isEmpty()
|
||||
}
|
||||
|
||||
fun changeVehicle(
|
||||
odometer: String,
|
||||
endLat: String,
|
||||
endLng: String,
|
||||
listener: WorkdayEndInterface
|
||||
) {
|
||||
val reqString = (Build.MANUFACTURER
|
||||
+ " " + Build.MODEL + " " + Build.VERSION.RELEASE
|
||||
+ " " + VERSION_CODES::class.java.fields[Build.VERSION.SDK_INT].name)
|
||||
|
||||
val ifilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
|
||||
val batteryStatus: Intent = shareInstance!!.registerReceiver(null, ifilter)!!
|
||||
val level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
|
||||
val scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
|
||||
val batteryPct = level / scale.toDouble() * 100.0
|
||||
val battery = batteryPct.toInt()
|
||||
|
||||
api.endWorkday(
|
||||
preferencesHelper.workdayId.toString(),
|
||||
odometer,
|
||||
endLat,
|
||||
endLng,
|
||||
reqString,
|
||||
battery.toString()
|
||||
)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.map { response ->
|
||||
preferencesHelper.workdayStarted = false
|
||||
preferencesHelper.workdayId = 0
|
||||
response
|
||||
}
|
||||
.subscribe(object : ResourceObserver<ResponseBody>() {
|
||||
override fun onNext(response: ResponseBody) {
|
||||
listener.success(response)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
listener.failure(e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun getUser(): User {
|
||||
return userBox.all[0]
|
||||
}
|
||||
|
||||
fun logout() {
|
||||
preferencesHelper.tokenApi = null
|
||||
preferencesHelper.isEnableHerramientaSurvey = true
|
||||
preferencesHelper.workdayStarted = false
|
||||
preferencesHelper.orderInProgress = 0L
|
||||
|
||||
userBox.removeAll()
|
||||
checkListQuestionBox.removeAll()
|
||||
vehicleBox.removeAll()
|
||||
orderBox.removeAll()
|
||||
evidenceBox.removeAll()
|
||||
businessQuestionBox.removeAll()
|
||||
domesticQuestionBox.removeAll()
|
||||
negativeServiceReasonBox.removeAll()
|
||||
businessAnswerBox.removeAll()
|
||||
domesticAnswerBox.removeAll()
|
||||
savedAnswerBox.removeAll()
|
||||
orderProgressBox.removeAll()
|
||||
nextDayOrderBox.removeAll()
|
||||
|
||||
NotificationManagerCompat.from(context!!).cancelAll()
|
||||
}
|
||||
|
||||
fun validateLogOut(): Boolean {
|
||||
return orderProgressBox.query()
|
||||
.equal(OrderProgress_.isSent, false)
|
||||
.build()
|
||||
.find()
|
||||
.isEmpty()
|
||||
}
|
||||
|
||||
fun validateRenewSession() : Boolean {
|
||||
return orderBox.isEmpty
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.iesoluciones.siodrenax.services
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.google.firebase.messaging.FirebaseMessagingService
|
||||
import com.google.firebase.messaging.RemoteMessage
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import com.iesoluciones.siodrenax.api
|
||||
import com.iesoluciones.siodrenax.entities.Order
|
||||
import com.iesoluciones.siodrenax.orderBox
|
||||
import com.iesoluciones.siodrenax.utils.HelperUtil
|
||||
import com.iesoluciones.siodrenax.utils.NotificationUtils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.observers.ResourceObserver
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
class NotificationService: FirebaseMessagingService() {
|
||||
|
||||
companion object {
|
||||
const val UPDATE_UI = "update_ui"
|
||||
}
|
||||
|
||||
override fun onMessageReceived(remoteMessage: RemoteMessage) {
|
||||
super.onMessageReceived(remoteMessage)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ---------- Second way to launch notification (valid to foreground) ----------
|
||||
|
||||
val notification = remoteMessage.data
|
||||
|
||||
if(notification.containsKey("servicio_id")){
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
|
||||
api.getOrderInfo(notification["servicio_id"]!!)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeOn(Schedulers.newThread())
|
||||
.subscribe(object : ResourceObserver<Order>() {
|
||||
override fun onNext(order: Order) {
|
||||
if (order.id != 0L) {
|
||||
orderBox.put(order)
|
||||
|
||||
HelperUtil().downloadSketchs(filesDir.absolutePath, mutableListOf(order))
|
||||
|
||||
sendBroadcast(Intent(UPDATE_UI))
|
||||
|
||||
NotificationUtils().showNotification(
|
||||
resources.getString(R.string.app_name),
|
||||
resources.getString(R.string.notification_accept_succes_message)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
NotificationUtils().showNotification(
|
||||
resources.getString(R.string.app_name),
|
||||
resources.getString(R.string.notification_accept_success_refresh_message)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
}
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
package com.iesoluciones.siodrenax.utils;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
|
||||
import com.iesoluciones.siodrenax.R;
|
||||
|
||||
|
||||
/**
|
||||
* Creado por Informática Electoral Proceso Electoral 2017.
|
||||
* Gustavo@ie-soluciones.com
|
||||
*/
|
||||
|
||||
|
||||
public class CircularProgressButton extends androidx.appcompat.widget.AppCompatButton {
|
||||
|
||||
public interface ProgressListener {
|
||||
void onProgressStart();
|
||||
|
||||
void onProgressFinish();
|
||||
}
|
||||
|
||||
private final CircularProgressDrawable mInactiveDrawable;
|
||||
private final CircularProgressDrawable mActiveDrawable;
|
||||
private CircularProgressDrawable mCurrentDrawable;
|
||||
private final Vibrator mVibrator;
|
||||
private ProgressListener mProgressListener;
|
||||
private Animator currentAnimation;
|
||||
private boolean mHoldingDown;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
public CircularProgressButton(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setTransformationMethod(null);
|
||||
if (this.isInEditMode()) {
|
||||
this.mInactiveDrawable = null;
|
||||
this.mActiveDrawable = null;
|
||||
this.mVibrator = null;
|
||||
return;
|
||||
}
|
||||
this.mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
this.mActiveDrawable = this.mCurrentDrawable = new CircularProgressDrawable.Builder()
|
||||
.setRingWidth(this.getResources().getDimensionPixelOffset(R.dimen.drawable_ring_size))
|
||||
.setOutlineColor(this.getResources().getColor(R.color.colorAccent))
|
||||
.setCenterColor(this.getResources().getColor(R.color.colorAccent))
|
||||
.setRingColor(this.getResources().getColor(R.color.colorPrimaryDark))
|
||||
.setFillColor(this.getResources().getColor(R.color.colorPrimaryDark))
|
||||
.create();
|
||||
this.mInactiveDrawable = new CircularProgressDrawable.Builder()
|
||||
.setRingWidth(this.getResources().getDimensionPixelOffset(R.dimen.drawable_ring_size))
|
||||
.setOutlineColor(this.getResources().getColor(R.color.colorAccent))
|
||||
.setCenterColor(this.getResources().getColor(R.color.colorAccent))
|
||||
.setRingColor(this.getResources().getColor(R.color.colorPrimaryDark))
|
||||
.setFillColor(this.getResources().getColor(R.color.colorPrimaryDark))
|
||||
.create();
|
||||
this.post(() -> setBackground(mCurrentDrawable));
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("SuspiciousNameCombination")
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
// set height as long as the width so the widget is perfectly circular
|
||||
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressLint({"ClickableViewAccessibility", "MissingPermission"})
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (this.mCurrentDrawable == this.mInactiveDrawable) {
|
||||
// do no more
|
||||
return true;
|
||||
}
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
double distance = this.distanceFromCenter(event.getX(), event.getY());
|
||||
if (distance < this.getWidth() / 2F) {
|
||||
this.mVibrator.vibrate(VibrationEffect.createOneShot(25, 10));
|
||||
this.mHoldingDown = true;
|
||||
if (this.mProgressListener != null) {
|
||||
this.mProgressListener.onProgressStart();
|
||||
}
|
||||
if (this.currentAnimation != null) {
|
||||
this.currentAnimation.cancel();
|
||||
}
|
||||
this.currentAnimation = prepareStyle2Animation();
|
||||
this.currentAnimation.start();
|
||||
}
|
||||
}
|
||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
this.mHoldingDown = false;
|
||||
if (this.currentAnimation != null) {
|
||||
this.currentAnimation.cancel();
|
||||
}
|
||||
this.mCurrentDrawable.setProgress(0f);
|
||||
this.mCurrentDrawable.setCircleScale(0f);
|
||||
}
|
||||
if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
double distance = this.distanceFromCenter(event.getX(), event.getY());
|
||||
//if (event.getX() < 0 || event.getY() < 0 || event.getX() > this.getWidth() || event.getY() > this.getHeight())
|
||||
if (distance > this.getWidth() / 2F) {
|
||||
this.mHoldingDown = false;
|
||||
if (this.currentAnimation != null) {
|
||||
this.currentAnimation.cancel();
|
||||
}
|
||||
this.mCurrentDrawable.setProgress(0f);
|
||||
this.mCurrentDrawable.setCircleScale(0f);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private double distanceFromCenter(float touchX, float touchY) {
|
||||
// get centers
|
||||
int centerX = this.getWidth() / 2;
|
||||
int centerY = this.getHeight() / 2;
|
||||
// calculate distances
|
||||
float distanceX = touchX - centerX;
|
||||
float distanceY = touchY - centerY;
|
||||
// pitagora suichi!
|
||||
return Math.sqrt((distanceX * distanceX) + (distanceY * distanceY));
|
||||
}
|
||||
|
||||
/* ownmeth */
|
||||
public void setProgressListener(ProgressListener progressListener) {
|
||||
this.mProgressListener = progressListener;
|
||||
}
|
||||
|
||||
public ProgressListener getProgressListener() {
|
||||
return this.mProgressListener;
|
||||
}
|
||||
|
||||
public void activate() {
|
||||
this.mCurrentDrawable = this.mActiveDrawable;
|
||||
this.setBackground(this.mCurrentDrawable);
|
||||
}
|
||||
|
||||
public void deactivate() {
|
||||
this.mCurrentDrawable = this.mInactiveDrawable;
|
||||
this.setBackground(this.mCurrentDrawable);
|
||||
}
|
||||
|
||||
private Animator prepareStyle2Animation() {
|
||||
AnimatorSet animation = new AnimatorSet();
|
||||
final ObjectAnimator progressAnimation = ObjectAnimator.ofFloat(this.mCurrentDrawable, CircularProgressDrawable.PROGRESS_PROPERTY, 0f, 1f);
|
||||
progressAnimation.setDuration(750);
|
||||
progressAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
|
||||
Animator innerCircleAnimation = ObjectAnimator.ofFloat(this.mCurrentDrawable, CircularProgressDrawable.CIRCLE_SCALE_PROPERTY, 0f, 1f);
|
||||
innerCircleAnimation.setDuration(500);
|
||||
innerCircleAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
final CircularProgressButton $this = CircularProgressButton.this;
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
// catch and ignore possible npe's due to ui refreshing
|
||||
try {
|
||||
if ($this.mProgressListener instanceof Fragment) {
|
||||
((Fragment) $this.mProgressListener).getActivity().getApplicationContext();
|
||||
}
|
||||
if ($this.mProgressListener instanceof Activity) {
|
||||
((Activity) $this.mProgressListener).getApplicationContext();
|
||||
}
|
||||
$this.mVibrator.vibrate(VibrationEffect.createOneShot(25, 10));
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
// catch and ignore possible npe's due to ui refreshing
|
||||
try {
|
||||
if ($this.mProgressListener instanceof Fragment) {
|
||||
((Fragment) $this.mProgressListener).getActivity().getApplicationContext();
|
||||
}
|
||||
if ($this.mProgressListener instanceof Activity) {
|
||||
((Activity) $this.mProgressListener).getApplicationContext();
|
||||
}
|
||||
if ($this.mHoldingDown) {
|
||||
$this.mVibrator.vibrate(VibrationEffect.createOneShot(100, 10));
|
||||
if ($this.mProgressListener != null) {
|
||||
$this.mProgressListener.onProgressFinish();
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
});
|
||||
animation.playSequentially(progressAnimation, innerCircleAnimation);
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,419 @@
|
||||
package com.iesoluciones.siodrenax.utils;
|
||||
|
||||
/*
|
||||
* Created by iedeveloper on 14/12/17.
|
||||
*/
|
||||
|
||||
import android.graphics.BlurMaskFilter;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
/**
|
||||
* Circular Progress Drawable.
|
||||
* <p>
|
||||
* This drawable will produce a circular shape with a ring surrounding it. The ring can appear
|
||||
* both filled and give a little cue when it is empty.
|
||||
* <p>
|
||||
* The inner circle size, the progress of the outer ring and if it is loading parameters can be
|
||||
* controlled, as well the different colors for the three components.
|
||||
*
|
||||
* @author Saul Diaz <sefford@gmail.com>
|
||||
*/
|
||||
public class CircularProgressDrawable extends Drawable {
|
||||
/**
|
||||
* Factor to convert the factor to paint the arc.
|
||||
* <p>
|
||||
* In this way the developer can use a more user-friendly [0..1f] progress
|
||||
*/
|
||||
public static final int PROGRESS_FACTOR = 360;
|
||||
/**
|
||||
* Property Inner Circle Scale.
|
||||
* <p>
|
||||
* The inner ring is supposed to defaults stay 3/4 radius off the outer ring at (75% scale), but this
|
||||
* property can make it grow or shrink via this equation: OuterRadius * Scale.
|
||||
* <p>
|
||||
* A 100% scale will make the inner circle to be the same radius as the outer ring.
|
||||
*/
|
||||
public static final String CIRCLE_SCALE_PROPERTY = "circleScale";
|
||||
/**
|
||||
* Property Progress of the outer circle.
|
||||
* <p>
|
||||
* The progress of the circle. If {@link #setIndeterminate(boolean) indeterminate flag} is set
|
||||
* to FALSE, this property will be used to indicate the completion of the outer circle [0..1f].
|
||||
* <p>
|
||||
* If set to TRUE, the drawable will activate the loading mode, where the drawable will
|
||||
* show a 90º arc which will be spinning around the outer circle as much as progress goes.
|
||||
*/
|
||||
public static final String PROGRESS_PROPERTY = "progress";
|
||||
/**
|
||||
* Property Ring color.
|
||||
* <p>
|
||||
* Changes the ring filling color
|
||||
*/
|
||||
public static final String RING_COLOR_PROPERTY = "ringColor";
|
||||
/**
|
||||
* Property circle color.
|
||||
* <p>
|
||||
* Changes the inner circle color
|
||||
*/
|
||||
public static final String CIRCLE_COLOR_PROPERTY = "circleColor";
|
||||
/**
|
||||
* Property outline color.
|
||||
* <p>
|
||||
* Changes the outline of the ring color.
|
||||
*/
|
||||
public static final String OUTLINE_COLOR_PROPERTY = "outlineColor";
|
||||
/**
|
||||
* Logger Tag for Logging purposes.
|
||||
*/
|
||||
public static final String TAG = "CircularProgressDrawable";
|
||||
/**
|
||||
* Paint object to draw the element.
|
||||
*/
|
||||
private final Paint paint;
|
||||
/**
|
||||
* Ring progress.
|
||||
*/
|
||||
protected float progress;
|
||||
/**
|
||||
* Color for the empty outer ring.
|
||||
*/
|
||||
protected int outlineColor;
|
||||
/**
|
||||
* Color for the completed ring.
|
||||
*/
|
||||
protected int ringColor;
|
||||
/**
|
||||
* Color for the inner circle.
|
||||
*/
|
||||
protected int centerColor;
|
||||
protected final int fillColor;
|
||||
/**
|
||||
* Rectangle where the filling ring will be drawn into.
|
||||
*/
|
||||
protected final RectF arcElements;
|
||||
/**
|
||||
* Width of the filling ring.
|
||||
*/
|
||||
protected final int ringWidth;
|
||||
/**
|
||||
* Scale of the inner circle. It will affect the inner circle size on this equation:
|
||||
* ([Biggest length of the Drawable] / 2) - (ringWidth / 2) * scale.
|
||||
*/
|
||||
protected float circleScale;
|
||||
/**
|
||||
* Set if it is an indeterminate
|
||||
*/
|
||||
protected boolean indeterminate;
|
||||
|
||||
/**
|
||||
* Creates a new CouponDrawable.
|
||||
*
|
||||
* @param ringWidth Width of the filled ring
|
||||
* @param circleScale Scale difference between the outer ring and the inner circle
|
||||
* @param outlineColor Color for the outline color
|
||||
* @param ringColor Color for the filled ring
|
||||
* @param centerColor Color for the center element
|
||||
*/
|
||||
CircularProgressDrawable(int ringWidth, float circleScale, int outlineColor, int ringColor, int centerColor, int fillColor) {
|
||||
this.progress = 0;
|
||||
this.outlineColor = outlineColor;
|
||||
this.ringColor = ringColor;
|
||||
this.centerColor = centerColor;
|
||||
this.fillColor = fillColor;
|
||||
this.paint = new Paint();
|
||||
this.paint.setAntiAlias(true);
|
||||
this.ringWidth = ringWidth;
|
||||
this.arcElements = new RectF();
|
||||
this.circleScale = circleScale;
|
||||
this.indeterminate = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
final Rect bounds = getBounds();
|
||||
// Calculations on the different components sizes
|
||||
int size = Math.min(bounds.height(), bounds.width());
|
||||
float outerRadius = (size / 2F) - (ringWidth / 2F);
|
||||
float innerRadius = outerRadius * circleScale;
|
||||
float offsetX = (bounds.width() - outerRadius * 2) / 2;
|
||||
float offsetY = (bounds.height() - outerRadius * 2) / 2;
|
||||
// Outline Circle
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(1);
|
||||
paint.setColor(outlineColor);
|
||||
canvas.drawCircle(bounds.centerX(), bounds.centerY(), outerRadius, paint);
|
||||
// Fill circle
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
paint.setColor(centerColor);
|
||||
canvas.drawCircle(bounds.centerX(), bounds.centerY(), outerRadius, paint);
|
||||
// Inner circle
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
paint.setColor(fillColor);
|
||||
paint.setAlpha(255);
|
||||
paint.setMaskFilter(new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL));
|
||||
canvas.drawCircle(bounds.centerX(), bounds.centerY(), innerRadius, paint);
|
||||
paint.setMaskFilter(null);
|
||||
int halfRingWidth = ringWidth / 2;
|
||||
float arcX0 = offsetX + halfRingWidth;
|
||||
float arcY0 = offsetY + halfRingWidth;
|
||||
float arcX = offsetX + outerRadius * 2 - halfRingWidth;
|
||||
float arcY = offsetY + outerRadius * 2 - halfRingWidth;
|
||||
// Outer Circle
|
||||
paint.setColor(ringColor);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(ringWidth);
|
||||
paint.setStrokeCap(Paint.Cap.ROUND);
|
||||
arcElements.set(arcX0, arcY0, arcX, arcY);
|
||||
if (indeterminate) {
|
||||
canvas.drawArc(arcElements, progress, 90, false, paint);
|
||||
} else {
|
||||
canvas.drawArc(arcElements, 360 - 90, progress, false, paint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
paint.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
paint.setColorFilter(cf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return 1 - paint.getAlpha();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the progress of the outer ring.
|
||||
* <p>
|
||||
* Will output a correct value only when the indeterminate mode is set to FALSE.
|
||||
*
|
||||
* @return Progress of the outer ring.
|
||||
*/
|
||||
public float getProgress() {
|
||||
return progress / PROGRESS_FACTOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress [0..1f]
|
||||
*
|
||||
* @param progress Sets the progress
|
||||
*/
|
||||
public void setProgress(float progress) {
|
||||
if (indeterminate) {
|
||||
this.progress = progress;
|
||||
} else {
|
||||
this.progress = PROGRESS_FACTOR * progress;
|
||||
}
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the inner circle scale.
|
||||
*
|
||||
* @return Inner circle scale in float multiplier.
|
||||
*/
|
||||
public float getCircleScale() {
|
||||
return circleScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the inner circle scale.
|
||||
*
|
||||
* @param circleScale Inner circle scale.
|
||||
*/
|
||||
public void setCircleScale(float circleScale) {
|
||||
this.circleScale = circleScale;
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the indeterminate status of the Drawable
|
||||
*
|
||||
* @return TRUE if the Drawable is in indeterminate mode or FALSE if it is in progress mode.
|
||||
*/
|
||||
public boolean isIndeterminate() {
|
||||
return indeterminate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the indeterminate parameter.
|
||||
* <p>
|
||||
* The indeterminate parameter will change the behavior of the Drawable. If the indeterminate
|
||||
* mode is set to FALSE, the outer ring will be able to be filled by using {@link #setProgress(float) setProgress}.
|
||||
* <p>
|
||||
* Otherwise the drawable will enter "loading mode" and a 90º arc will be able to be spinned around
|
||||
* the inner circle.
|
||||
* <p>
|
||||
* <b>By default, indeterminate mode is set to FALSE.</b>
|
||||
*
|
||||
* @param indeterminate TRUE to activate loading mode. FALSE to activate progress mode.
|
||||
*/
|
||||
public void setIndeterminate(boolean indeterminate) {
|
||||
this.indeterminate = indeterminate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the outline color.
|
||||
*
|
||||
* @return Outline color of the empty ring.
|
||||
*/
|
||||
public int getOutlineColor() {
|
||||
return outlineColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filled ring color.
|
||||
*
|
||||
* @return Returns the filled ring color.
|
||||
*/
|
||||
public int getRingColor() {
|
||||
return ringColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color of the inner circle.
|
||||
*
|
||||
* @return Inner circle color.
|
||||
*/
|
||||
public int getCenterColor() {
|
||||
return centerColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the empty progress outline color.
|
||||
*
|
||||
* @param outlineColor Outline color in #AARRGGBB format.
|
||||
*/
|
||||
public void setOutlineColor(int outlineColor) {
|
||||
this.outlineColor = outlineColor;
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress ring color.
|
||||
*
|
||||
* @param ringColor Ring color in #AARRGGBB format.
|
||||
*/
|
||||
public void setRingColor(int ringColor) {
|
||||
this.ringColor = ringColor;
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the inner circle color.
|
||||
*
|
||||
* @param centerColor Inner circle color in #AARRGGBB format.
|
||||
*/
|
||||
public void setCenterColor(int centerColor) {
|
||||
this.centerColor = centerColor;
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to manage the creation of a CircularProgressDrawable
|
||||
*
|
||||
* @author Saul Diaz <sefford@gmail.com>
|
||||
*/
|
||||
public static class Builder {
|
||||
/**
|
||||
* Witdh of the stroke of the filled ring
|
||||
*/
|
||||
int ringWidth;
|
||||
/**
|
||||
* Color of the outline of the empty ring in #AARRGGBB mode.
|
||||
*/
|
||||
int outlineColor;
|
||||
/**
|
||||
* Color of the filled ring in #AARRGGBB mode.
|
||||
*/
|
||||
int ringColor;
|
||||
/**
|
||||
* Color of the inner circle in #AARRGGBB mode.
|
||||
*/
|
||||
int centerColor;
|
||||
int fillcolor;
|
||||
/**
|
||||
* Scale between the outer ring and the inner circle
|
||||
*/
|
||||
float circleScale = 0f;
|
||||
|
||||
/**
|
||||
* Sets the ring width.
|
||||
*
|
||||
* @param ringWidth Default ring width
|
||||
* @return This builder
|
||||
*/
|
||||
public Builder setRingWidth(int ringWidth) {
|
||||
this.ringWidth = ringWidth;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default empty outer ring outline color.
|
||||
*
|
||||
* @param outlineColor Outline color in #AARRGGBB format.
|
||||
* @return This Builder
|
||||
*/
|
||||
public Builder setOutlineColor(int outlineColor) {
|
||||
this.outlineColor = outlineColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress ring color.
|
||||
*
|
||||
* @param ringColor Ring color in #AARRGGBB format.
|
||||
* @return This Builder
|
||||
*/
|
||||
public Builder setRingColor(int ringColor) {
|
||||
this.ringColor = ringColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the inner circle color.
|
||||
*
|
||||
* @param centerColor Inner circle color in #AARRGGBB format.
|
||||
* @return This builder
|
||||
*/
|
||||
public Builder setCenterColor(int centerColor) {
|
||||
this.centerColor = centerColor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFillColor(int fillcolor) {
|
||||
this.fillcolor = fillcolor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the inner circle scale. Defaults to 0.75.
|
||||
*
|
||||
* @param circleScale Inner circle scale.
|
||||
* @return This builder
|
||||
*/
|
||||
public Builder setInnerCircleScale(float circleScale) {
|
||||
this.circleScale = circleScale;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CircularProgressDrawable with the requested parameters
|
||||
*
|
||||
* @return New CircularProgressDrawableInstance
|
||||
*/
|
||||
public com.iesoluciones.siodrenax.utils.CircularProgressDrawable create() {
|
||||
return new com.iesoluciones.siodrenax.utils.CircularProgressDrawable(ringWidth, circleScale, outlineColor, ringColor, centerColor, fillcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.iesoluciones.siodrenax.utils
|
||||
|
||||
class Constants {
|
||||
|
||||
companion object {
|
||||
const val LOGGED_IN = 1
|
||||
const val WORKDAY_STARTED=2
|
||||
const val NO_SESSION = 3
|
||||
const val ORDER_IN_PROGRESS = 4
|
||||
const val LOGGED_IN_MANAGER = 5
|
||||
const val WORKDAY_STARTED_MANAGER = 6
|
||||
|
||||
const val APP_ID = "MOVIL"
|
||||
|
||||
const val EMPLOYEE_MANAGER: Long = 6
|
||||
|
||||
// CheckList
|
||||
const val REVISION = "REVISION"
|
||||
const val MATERIAL = "MATERIAL"
|
||||
const val HERRAMIENTA = "HERRAMIENTA"
|
||||
const val WORKDAY = "WORKDAY"
|
||||
|
||||
// Evidences
|
||||
const val EVIDENCE_START = 1
|
||||
const val EVIDENCE_PROCESS = 2
|
||||
const val EVIDENCE_FINAL = 3
|
||||
|
||||
// Location
|
||||
const val DEFAULT_LATITUDE = 24.7726885
|
||||
const val DEFAULT_LONGITUDE = -107.4434088
|
||||
|
||||
// Notifications
|
||||
const val ORDER_ID = "servicio_id"
|
||||
|
||||
// Survey
|
||||
const val ID_SERVICE_TYPE_DOMESTIC: Long = 1L
|
||||
|
||||
// Parameters
|
||||
const val DEFAULT_LITERS: String = "0"
|
||||
const val HIDE_ALPHA = 0f
|
||||
const val HIDE_DURATION = 200L
|
||||
const val SHOW_ALPHA = 1f
|
||||
const val SHOW_DURATION = 300L
|
||||
|
||||
// OrderDetail
|
||||
const val EVIDENCE_ID: String = "evidence_id"
|
||||
const val EVIDENCE_NAME: String = "evidence_name"
|
||||
const val MILEAGE = "mileage"
|
||||
const val IDSERVICETYPEDOMESTIC = 1L
|
||||
const val EVIDENCE_CODE = 2
|
||||
const val SIGNATURE_CODE = 10
|
||||
const val SURVEY_CODE = 20
|
||||
const val REQUEST_PERMISSIONS_REQUEST_CODE = 33
|
||||
|
||||
// Camera
|
||||
const val COMPRESS_JPEG_QUALITY_LOW: Int = 15
|
||||
const val EVIDENCIA = "Evidencia "
|
||||
const val SHOW_TITLE_ALPHA = 0f
|
||||
const val SHOW_TITLE_DURATION = 200L
|
||||
const val SHOW_TITLE_DELAY = 1000L
|
||||
|
||||
// Survey
|
||||
const val PDF_URL = "http://drenax.mx/assets/documents/aviso_privacidad.pdf"
|
||||
const val DRIVE_READER = "https://drive.google.com/viewerng/viewer?embedded=true&url="
|
||||
|
||||
// Answer Type
|
||||
const val ANSWER_CHECKBOX = 1
|
||||
const val ANSWER_DATE = 2
|
||||
const val ANSWER_EMAIL = 3
|
||||
const val ANSWER_CURRENCY = 4
|
||||
const val ANSWER_NUMBER = 5
|
||||
const val ANSWER_TEXT = 6
|
||||
|
||||
// Notifications
|
||||
const val EXTRA_NOTIFICATION_CLICKED: String = "notificationClicked"
|
||||
|
||||
// MultipleViewHolderAdapter
|
||||
const val CERO = "0"
|
||||
|
||||
// Signature
|
||||
const val ANIMATE_FADE_OUT_ALPHA = 0.0f
|
||||
const val ANIMATE_FADE_OUT_DURATION = 200L
|
||||
const val ANIMATE_FADE_IN_DURATION = 200L
|
||||
const val ANIMATE_FADE_IN_ALPHA = 1.0f
|
||||
|
||||
//Manager
|
||||
const val OPERATOR_ID: String = "operator_id"
|
||||
const val OPERATOR_NAME = "operator_name"
|
||||
|
||||
//ZIP
|
||||
const val BUFFER_SIZE = 6 * 1024
|
||||
|
||||
//SKETCH
|
||||
const val BUFFER_SIZE_SKETCH = 1024 * 1024
|
||||
const val BRANCH_NAME = "branch_name"
|
||||
const val SKETCH_PATH = "sketch_path"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.iesoluciones.siodrenax.utils
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.app.Dialog
|
||||
import android.app.ProgressDialog
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import com.iesoluciones.siodrenax.R
|
||||
|
||||
class CustomDialogFragment(context: Context) {
|
||||
|
||||
private var mContext: Context = context
|
||||
private lateinit var mDialog: ProgressDialog
|
||||
private lateinit var mMessage: String
|
||||
private lateinit var mTitle: String
|
||||
private lateinit var mSubtitle: String
|
||||
private lateinit var mTitleCloseButton: String
|
||||
private var mSelection = 0
|
||||
private lateinit var mArrayMessage: Array<String>
|
||||
private lateinit var mViewType: MessageViewType
|
||||
private lateinit var mView: View
|
||||
|
||||
enum class MessageViewType {
|
||||
RADIOBUTTON, DIALOG, ALERTDIALOG, WEBVIEWDIALOG
|
||||
}
|
||||
|
||||
|
||||
fun setTitle(title: String): CustomDialogFragment {
|
||||
this.mTitle = title
|
||||
return this
|
||||
}
|
||||
|
||||
fun messageType(messageViewType: MessageViewType): CustomDialogFragment {
|
||||
mViewType = messageViewType
|
||||
return this
|
||||
}
|
||||
|
||||
fun show() {
|
||||
when (mViewType) {
|
||||
MessageViewType.RADIOBUTTON -> showRadioButtonMessage(mTitle, mArrayMessage)
|
||||
MessageViewType.DIALOG -> showDialog(mTitle, mSubtitle)
|
||||
MessageViewType.ALERTDIALOG -> showAlertDialogMessage(
|
||||
mTitle,
|
||||
mMessage,
|
||||
mTitleCloseButton
|
||||
)
|
||||
MessageViewType.WEBVIEWDIALOG -> showWebViewDialog(mView)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showRadioButtonMessage(titulo: String, arrayMessage: Array<String>) {
|
||||
val builder = AlertDialog.Builder(mContext)
|
||||
builder.setTitle(titulo)
|
||||
builder.setSingleChoiceItems(
|
||||
arrayMessage, 1
|
||||
) { _, which ->
|
||||
mSelection = which
|
||||
}
|
||||
builder.setNegativeButton(
|
||||
mContext.getString(R.string.cancel)
|
||||
) { _, _ -> }
|
||||
builder.setPositiveButton(
|
||||
mContext.getString(R.string.accept)
|
||||
) { _, _ -> }
|
||||
val alert = builder.create()
|
||||
alert.setCanceledOnTouchOutside(false)
|
||||
alert.show()
|
||||
}
|
||||
|
||||
fun showRadioButtonMessage(
|
||||
titulo: String,
|
||||
arrayMessage: Array<String>,
|
||||
onClickActionButton: OnClickActionButton
|
||||
): Dialog {
|
||||
val builder = AlertDialog.Builder(mContext, R.style.DialogMessageTheme)
|
||||
builder.setTitle(titulo)
|
||||
builder.setSingleChoiceItems(arrayMessage, 0) { _, which -> mSelection = which }
|
||||
builder.setPositiveButton(mContext.getString(R.string.accept)) { _, _ ->
|
||||
onClickActionButton.onPositiveRadioButtonClicked(
|
||||
mSelection
|
||||
)
|
||||
}
|
||||
builder.setCancelable(false)
|
||||
builder.setNegativeButton(mContext.getString(R.string.cancel)) { _, _ -> onClickActionButton.onNegativeButtonClicked() }
|
||||
return builder.create()
|
||||
}
|
||||
|
||||
private fun showDialog(titulo: String, descripcion: String) {
|
||||
if (mDialog.isShowing)
|
||||
mDialog.dismiss()
|
||||
|
||||
mDialog = ProgressDialog(mContext, R.style.DialogMessageTheme)
|
||||
mDialog.setTitle(titulo)
|
||||
mDialog.setMessage(descripcion)
|
||||
mDialog.setCancelable(false)
|
||||
mDialog.setCanceledOnTouchOutside(false)
|
||||
mDialog.show()
|
||||
}
|
||||
|
||||
private fun showWebViewDialog(view: View) {
|
||||
if (mDialog.isShowing)
|
||||
mDialog.dismiss()
|
||||
|
||||
mDialog = ProgressDialog(mContext, R.style.DialogMessageTheme)
|
||||
mDialog.setView(view)
|
||||
mDialog.setCancelable(false)
|
||||
mDialog.setCanceledOnTouchOutside(false)
|
||||
mDialog.show()
|
||||
}
|
||||
|
||||
private fun showAlertDialogMessage(
|
||||
title: String,
|
||||
message: String,
|
||||
positiveButton: String
|
||||
): Dialog {
|
||||
val builder = AlertDialog.Builder(mContext)
|
||||
builder.setTitle(title)
|
||||
builder.setMessage(message)
|
||||
builder.setPositiveButton(positiveButton) { _, _ -> }
|
||||
return builder.create()
|
||||
}
|
||||
|
||||
interface OnClickActionButton {
|
||||
fun onPositiveRadioButtonClicked(selection: Int)
|
||||
fun onPositiveButtonClicked()
|
||||
fun onNegativeButtonClicked()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.iesoluciones.siodrenax.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.print.PdfPrinter
|
||||
import android.print.PrintAttributes
|
||||
import android.print.PrintDocumentAdapter
|
||||
import android.webkit.WebChromeClient
|
||||
import android.webkit.WebView
|
||||
import androidx.annotation.UiThread
|
||||
import java.io.File
|
||||
|
||||
class CustomHtmlToPdfConvertor(private val context: Context) {
|
||||
|
||||
private var baseUrl: String? = null
|
||||
|
||||
fun setBaseUrl(baseUrl: String) {
|
||||
this.baseUrl = baseUrl
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun convert(
|
||||
pdfLocation: File,
|
||||
htmlString: String,
|
||||
onPdfGenerationFailed: PdfGenerationFailedCallback? = null,
|
||||
onPdfGenerated: PdfGeneratedCallback,
|
||||
) {
|
||||
|
||||
// maintain pdf generation status
|
||||
var pdfGenerationStarted = false
|
||||
try {
|
||||
|
||||
// create new webview
|
||||
val pdfWebView = WebView(context)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
pdfWebView.settings.safeBrowsingEnabled = false
|
||||
}
|
||||
|
||||
// job name
|
||||
val jobName = Math.random().toString()
|
||||
|
||||
// generate pdf attributes and properties
|
||||
val attributes = getPrintAttributes()
|
||||
|
||||
// generate print document adapter
|
||||
val printAdapter = getPrintAdapter(pdfWebView, jobName)
|
||||
|
||||
pdfWebView.webChromeClient = object : WebChromeClient() {
|
||||
override fun onProgressChanged(view: WebView, newProgress: Int) {
|
||||
super.onProgressChanged(view, newProgress)
|
||||
|
||||
// some times progress provided by this method is wrong, that's why we are getting progress directly provided by WebView
|
||||
val progress = pdfWebView.progress
|
||||
|
||||
|
||||
// when page is fully loaded, start creating PDF
|
||||
if (progress == 100 && !pdfGenerationStarted) {
|
||||
|
||||
// change the status of pdf generation
|
||||
pdfGenerationStarted = true
|
||||
|
||||
// generate pdf
|
||||
val pdfPrinter = PdfPrinter(attributes)
|
||||
pdfPrinter.generate(printAdapter, pdfLocation, onPdfGenerated)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// load html in WebView when it's setup is completed
|
||||
pdfWebView.loadDataWithBaseURL(baseUrl, htmlString, "text/html", "utf-8", null)
|
||||
|
||||
} catch (e: Exception) {
|
||||
onPdfGenerationFailed?.invoke(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getPrintAdapter(pdfWebView: WebView, jobName: String): PrintDocumentAdapter {
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
pdfWebView.createPrintDocumentAdapter(jobName)
|
||||
} else {
|
||||
pdfWebView.createPrintDocumentAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPrintAttributes(): PrintAttributes {
|
||||
return PrintAttributes.Builder().apply {
|
||||
setMediaSize(PrintAttributes.MediaSize.NA_LETTER)
|
||||
setResolution(PrintAttributes.Resolution("pdf", Context.PRINT_SERVICE, 100, 100))
|
||||
setMinMargins(PrintAttributes.Margins.NO_MARGINS)
|
||||
}.build()
|
||||
}
|
||||
}
|
||||
|
||||
private typealias PdfGeneratedCallback = (File) -> Unit
|
||||
private typealias PdfGenerationFailedCallback = (Exception) -> Unit
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.iesoluciones.siodrenax.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.iesoluciones.siodrenax.R
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.text.DecimalFormat
|
||||
|
||||
fun Activity.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) =
|
||||
Toast.makeText(this, message, duration).show()
|
||||
|
||||
fun Activity.toastLong(message: CharSequence, duration: Int = Toast.LENGTH_LONG) =
|
||||
Toast.makeText(this, message, duration).show()
|
||||
|
||||
fun Activity.toast(resourceId: Int, duration: Int = Toast.LENGTH_SHORT) =
|
||||
Toast.makeText(this, resourceId, duration).show()
|
||||
|
||||
fun Activity.snackBar(
|
||||
message: CharSequence,
|
||||
view: View? = findViewById(R.id.container),
|
||||
duration: Int = Snackbar.LENGTH_SHORT,
|
||||
action: String? = null,
|
||||
actionEvt: (v: View) -> Unit = {}
|
||||
) {
|
||||
|
||||
if (view != null) {
|
||||
val snackBar = Snackbar.make(view, message, duration)
|
||||
if (!action.isNullOrEmpty()) {
|
||||
snackBar.setAction(action, actionEvt)
|
||||
}
|
||||
snackBar.show()
|
||||
}
|
||||
}
|
||||
|
||||
fun ViewGroup.inflate(layoutId: Int) = LayoutInflater.from(context).inflate(layoutId, this, false)!!
|
||||
|
||||
inline fun <reified T : Activity> Activity.goToActivity(noinline init: Intent.() -> Unit = {}) {
|
||||
val intent = Intent(this, T::class.java)
|
||||
intent.init()
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
fun String.currencyFormat(): String {
|
||||
return try {
|
||||
val formatter = DecimalFormat("###,###,##0.00")
|
||||
formatter.format(this.toDouble())
|
||||
} catch (e: Exception) {
|
||||
"0.00"
|
||||
}
|
||||
}
|
||||
|
||||
fun Path.exists(): Boolean = Files.exists(this)
|
||||
|
||||
fun Path.isFile(): Boolean = !Files.isDirectory(this)
|
||||
|
||||
fun Path.delete(): Boolean {
|
||||
return if (isFile() && exists()) {
|
||||
//Actual delete operation
|
||||
Files.delete(this)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
val Any.TAG: String
|
||||
get() {
|
||||
val tag = javaClass.simpleName
|
||||
return if (tag.length <= 23) tag else tag.substring(0, 23)
|
||||
}
|
||||
464
app/src/main/java/com/iesoluciones/siodrenax/utils/HelperUtil.kt
Normal file
464
app/src/main/java/com/iesoluciones/siodrenax/utils/HelperUtil.kt
Normal file
@@ -0,0 +1,464 @@
|
||||
package com.iesoluciones.siodrenax.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.StrictMode
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import com.iesoluciones.siodrenax.*
|
||||
import com.iesoluciones.siodrenax.App.Companion.context
|
||||
import com.iesoluciones.siodrenax.activities.LoginActivity
|
||||
import com.iesoluciones.siodrenax.entities.*
|
||||
import com.iesoluciones.siodrenax.fragments.dialogs.IncidentsInputFragment
|
||||
import com.iesoluciones.siodrenax.fragments.dialogs.MileageInputDialogFragment
|
||||
import com.iesoluciones.siodrenax.fragments.dialogs.VehicleIncidentsFragment
|
||||
import com.iesoluciones.siodrenax.interfaces.OnIncidentListener
|
||||
import com.iesoluciones.siodrenax.interfaces.OnIncidentShowListener
|
||||
import com.iesoluciones.siodrenax.interfaces.OnMileageListener
|
||||
import com.iesoluciones.siodrenax.network.HttpError
|
||||
import com.iesoluciones.siodrenax.network.UnprocessableEntity
|
||||
import com.iesoluciones.siodrenax.repositories.WorkdayRepository
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.BUFFER_SIZE
|
||||
import com.iesoluciones.siodrenax.utils.Constants.Companion.BUFFER_SIZE_SKETCH
|
||||
import com.iesoluciones.siodrenax.workers.SyncWorker
|
||||
import retrofit2.HttpException
|
||||
import java.io.*
|
||||
import java.net.*
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
import javax.net.ssl.SSLPeerUnverifiedException
|
||||
|
||||
|
||||
class HelperUtil {
|
||||
|
||||
private val tagIncidenceDialog = "incidenceDialog"
|
||||
private val tagShowIncidenceDialog = "showIncidenceDialog"
|
||||
private val tagMileageDialog = "mileageDialog"
|
||||
|
||||
fun parseError(context: Context, e: Throwable) {
|
||||
|
||||
if (e is HttpException) {
|
||||
when (e.code()) {
|
||||
401, 400, 403, 404, 405, 423 -> {
|
||||
val error: HttpError? = HttpError.parseException(e)
|
||||
if (error != null) {
|
||||
AlertDialog.Builder(context, R.style.MyAlertDialogStyle)
|
||||
.setMessage(error.error)
|
||||
.setTitle(R.string.title_error)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(
|
||||
App.shareInstance!!.resources.getString(R.string.button_ok),
|
||||
null
|
||||
)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
420 -> {
|
||||
val error: HttpError? = HttpError.parseException(e)
|
||||
if (error != null) {
|
||||
val workdayRepository = WorkdayRepository()
|
||||
if (workdayRepository.validateRenewSession()) {
|
||||
AlertDialog.Builder(context, R.style.MyAlertDialogStyle)
|
||||
.setMessage(R.string.session_expired_message)
|
||||
.setTitle(R.string.session_expired)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(App.shareInstance!!.resources.getString(R.string.button_renew_session)) { _, _ ->
|
||||
workdayRepository.logout()
|
||||
val intent = Intent(context, LoginActivity::class.java);
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
(context as Activity).startActivity(intent)
|
||||
(context as Activity).finish()
|
||||
}
|
||||
.show()
|
||||
} else {
|
||||
AlertDialog.Builder(context, R.style.MyAlertDialogStyle)
|
||||
.setMessage(R.string.session_expired_with_orders_message)
|
||||
.setTitle(R.string.session_expired)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(App.shareInstance!!.resources.getString(R.string.button_ok), null)
|
||||
.show()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
422 -> {
|
||||
val errors = UnprocessableEntity.parseException(e)
|
||||
AlertDialog.Builder(context, R.style.MyAlertDialogStyle)
|
||||
.setMessage(errors!!.errors[0])
|
||||
.setTitle(errors.message)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(
|
||||
App.shareInstance!!.resources.getString(R.string.button_ok),
|
||||
null
|
||||
)
|
||||
.show()
|
||||
}
|
||||
500 -> AlertDialog.Builder(context, R.style.MyAlertDialogStyle)
|
||||
.setMessage(App.shareInstance!!.resources.getString(R.string.unexpected_error))
|
||||
.setTitle(App.shareInstance!!.resources.getString(R.string.title_error))
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(context.resources.getString(R.string.button_ok), null)
|
||||
.show()
|
||||
}
|
||||
} else if (e is IOException) {
|
||||
when (e) {
|
||||
is ConnectException -> AlertDialog.Builder(context, R.style.MyAlertDialogStyle)
|
||||
.setMessage(App.shareInstance!!.resources.getString(R.string.unreachable_network))
|
||||
.setTitle(App.shareInstance!!.resources.getString(R.string.title_error))
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(
|
||||
App.shareInstance!!.resources.getString(R.string.button_ok),
|
||||
null
|
||||
)
|
||||
.setNeutralButton(App.shareInstance!!.resources.getString(R.string.network_settings)) { _, _ ->
|
||||
context.startActivity(Intent(Settings.ACTION_WIRELESS_SETTINGS))
|
||||
}.show()
|
||||
|
||||
is SocketException -> AlertDialog.Builder(context, R.style.MyAlertDialogStyle)
|
||||
.setMessage(App.shareInstance!!.resources.getString(R.string.unreachable_network))
|
||||
.setTitle(App.shareInstance!!.resources.getString(R.string.title_error))
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(
|
||||
App.shareInstance!!.resources.getString(R.string.button_ok),
|
||||
null
|
||||
)
|
||||
.setNeutralButton(App.shareInstance!!.resources.getString(R.string.network_settings)) { _, _ ->
|
||||
context.startActivity(Intent(Settings.ACTION_WIRELESS_SETTINGS))
|
||||
}.show()
|
||||
|
||||
is SocketTimeoutException -> AlertDialog.Builder(
|
||||
context,
|
||||
R.style.MyAlertDialogStyle
|
||||
)
|
||||
.setMessage(App.shareInstance!!.resources.getString(R.string.timeout))
|
||||
.setTitle(App.shareInstance!!.resources.getString(R.string.title_error))
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(
|
||||
App.shareInstance!!.resources.getString(R.string.button_ok),
|
||||
null
|
||||
)
|
||||
.show()
|
||||
|
||||
is UnknownHostException -> Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.unknown_host_exception),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
|
||||
is SSLPeerUnverifiedException -> AlertDialog.Builder(
|
||||
context,
|
||||
R.style.MyAlertDialogStyle
|
||||
)
|
||||
.setMessage(App.shareInstance!!.resources.getString(R.string.certificate_error_message))
|
||||
.setTitle(App.shareInstance!!.resources.getString(R.string.certificate_error))
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(
|
||||
App.shareInstance!!.resources.getString(R.string.button_ok),
|
||||
null
|
||||
)
|
||||
.show()
|
||||
|
||||
else -> Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.unexpected_error),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun incidentShowDialogFragment(
|
||||
fm: FragmentManager,
|
||||
listener: OnIncidentShowListener,
|
||||
incidence: String?
|
||||
) {
|
||||
val ft = fm.beginTransaction()
|
||||
val prev = fm.findFragmentByTag(tagShowIncidenceDialog)
|
||||
if (prev != null) {
|
||||
ft.remove(prev)
|
||||
}
|
||||
ft.addToBackStack(null)
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
val dialogFragment: DialogFragment = VehicleIncidentsFragment.newInstance(
|
||||
listener,
|
||||
incidence
|
||||
)
|
||||
dialogFragment.show(ft, tagShowIncidenceDialog)
|
||||
}, 500)
|
||||
}
|
||||
|
||||
fun createEvidences(order: Order) {
|
||||
|
||||
val evidence = evidenceBox.query()
|
||||
.equal(Evidence_.idOrder, order.id)
|
||||
.and().equal(Evidence_.idRequest, order.idRequest)
|
||||
.build()
|
||||
.findFirst()
|
||||
|
||||
if(evidence == null)
|
||||
this.createEvidenceHolders(order.id, order.idRequest)
|
||||
}
|
||||
|
||||
private fun createEvidenceHolders(idOrder: Long, idRequest: Long) {
|
||||
for (i in 1..9) {
|
||||
val evidence = Evidence()
|
||||
evidence.idOrder = idOrder
|
||||
evidence.idRequest = idRequest
|
||||
when (i) {
|
||||
1, 2, 3 -> {
|
||||
evidence.type = Constants.EVIDENCE_START
|
||||
evidence.evidenceNo = ((i.toString() + "").toLong())
|
||||
}
|
||||
4, 5, 6 -> {
|
||||
evidence.type = Constants.EVIDENCE_PROCESS
|
||||
evidence.evidenceNo = ((i - 3).toString() + "").toLong()
|
||||
}
|
||||
7, 8, 9 -> {
|
||||
evidence.type = Constants.EVIDENCE_FINAL
|
||||
evidence.evidenceNo = ((i - 6).toString() + "").toLong()
|
||||
}
|
||||
else -> {
|
||||
evidence.type = Constants.EVIDENCE_START + 1
|
||||
evidence.evidenceNo = (i.toString() + "").toLong()
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
evidenceBox.put(evidence)
|
||||
} catch (ex: Exception) {
|
||||
Log.e("CREAR EVIDENCIA", ex.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun mileageDialogFragment(fm: FragmentManager, listener: OnMileageListener) {
|
||||
val ft = fm.beginTransaction()
|
||||
val prev = fm.findFragmentByTag(tagMileageDialog)
|
||||
if (prev != null) {
|
||||
ft.remove(prev)
|
||||
}
|
||||
ft.addToBackStack(null)
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
val dialogFragment: DialogFragment =
|
||||
MileageInputDialogFragment.newInstance(listener)
|
||||
dialogFragment.show(ft, tagMileageDialog)
|
||||
|
||||
}, 0)
|
||||
}
|
||||
|
||||
fun incidentDialogFragment(fm: FragmentManager, listener: OnIncidentListener) {
|
||||
val ft = fm.beginTransaction()
|
||||
val prev = fm.findFragmentByTag(tagIncidenceDialog)
|
||||
if (prev != null) {
|
||||
ft.remove(prev)
|
||||
}
|
||||
ft.addToBackStack(null)
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
val dialogFragment: DialogFragment = IncidentsInputFragment.newInstance(listener)
|
||||
dialogFragment.show(ft, tagIncidenceDialog)
|
||||
}, 500)
|
||||
}
|
||||
|
||||
fun formatTime(millis: Long): String {
|
||||
val secs = millis / 1000
|
||||
|
||||
return String.format("%02d:%02d:%02d", secs / 3600, secs % 3600 / 60, secs % 60)
|
||||
}
|
||||
|
||||
fun decodeFromFile(path: String, sampleSize: Int): Bitmap {
|
||||
val options2 = BitmapFactory.Options()
|
||||
options2.inSampleSize = sampleSize
|
||||
|
||||
return if (sampleSize != 0) BitmapFactory.decodeFile(
|
||||
path,
|
||||
options2
|
||||
) else BitmapFactory.decodeFile(
|
||||
path,
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
fun saveBitmap(filePath: File, filename: String, bitmap: Bitmap): String? {
|
||||
val file = File(filePath, filename)
|
||||
val fos: FileOutputStream
|
||||
|
||||
try {
|
||||
fos = FileOutputStream(file)
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
|
||||
fos.flush()
|
||||
} catch (e: java.lang.Exception) {
|
||||
e.printStackTrace()
|
||||
return null
|
||||
}
|
||||
|
||||
return file.absolutePath
|
||||
}
|
||||
|
||||
fun startSync() {
|
||||
//System.gc()
|
||||
|
||||
val constraints = Constraints.Builder()
|
||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||
.build()
|
||||
|
||||
val syncWorker = OneTimeWorkRequest.Builder(SyncWorker::class.java)
|
||||
.setConstraints(constraints)
|
||||
.build()
|
||||
|
||||
Toast.makeText(
|
||||
context,
|
||||
context!!.getString(R.string.toast_sync_progress),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
|
||||
WorkManager.getInstance().enqueue(syncWorker)
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts first letter of Name and LastName sent in Params
|
||||
*
|
||||
* @param name Name
|
||||
* @param lastname Last Name
|
||||
* @return String with 2 Letters in UpperCase
|
||||
*/
|
||||
fun getInitials(name: String?, lastname: String?): String {
|
||||
var initials = ""
|
||||
if (name != null) if (name.isNotEmpty() && name.substring(0, 1) != " ") {
|
||||
initials += name.substring(0, 1)
|
||||
}
|
||||
if (lastname != null) if (lastname.isNotEmpty() && lastname.substring(0, 1) != " ") {
|
||||
initials += lastname.substring(0, 1)
|
||||
}
|
||||
return initials.toUpperCase(Locale.ROOT)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun zip(files: Array<String>, zipFile: String): String {
|
||||
var origin: BufferedInputStream?
|
||||
val out = ZipOutputStream(BufferedOutputStream(FileOutputStream(zipFile)))
|
||||
try {
|
||||
val data = ByteArray(BUFFER_SIZE)
|
||||
for (i in files.indices) {
|
||||
val fi = FileInputStream(files[i])
|
||||
origin = BufferedInputStream(fi, BUFFER_SIZE)
|
||||
try {
|
||||
val entry = ZipEntry(files[i].substring(files[i].lastIndexOf("/") + 1))
|
||||
out.putNextEntry(entry)
|
||||
var count: Int
|
||||
while (origin.read(data, 0, BUFFER_SIZE)
|
||||
.also { count = it } != -1
|
||||
) {
|
||||
out.write(data, 0, count)
|
||||
}
|
||||
} finally {
|
||||
origin.close()
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
out.close()
|
||||
}
|
||||
|
||||
return zipFile
|
||||
}
|
||||
|
||||
fun deleteFile(path: String): Boolean{
|
||||
val p = Paths.get(path)
|
||||
return p.delete()
|
||||
}
|
||||
|
||||
fun encodeBase64(filePath: String): String?{
|
||||
return try {
|
||||
val bytes = File(filePath).readBytes()
|
||||
Base64.getEncoder().encodeToString(bytes)
|
||||
}catch (e: Exception){
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun encodeBase64WithData(filePath: String): String?{
|
||||
return try {
|
||||
val bytes = File(filePath).readBytes()
|
||||
val base64 = Base64.getEncoder().encodeToString(bytes)
|
||||
val extension = filePath.split(".").last()
|
||||
"data:image/$extension;base64,$base64"
|
||||
}catch (e: Exception){
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun scaleBitmap(rotated: Bitmap, maxSize: Int = 300): Bitmap? {
|
||||
val outWidth: Int
|
||||
val outHeight: Int
|
||||
val inWidth = rotated.width
|
||||
val inHeight = rotated.height
|
||||
if (inWidth > inHeight) {
|
||||
outWidth = maxSize
|
||||
outHeight = inHeight * maxSize / inWidth
|
||||
} else {
|
||||
outHeight = maxSize
|
||||
outWidth = inWidth * maxSize / inHeight
|
||||
}
|
||||
|
||||
return Bitmap.createScaledBitmap(rotated, outWidth, outHeight, false)
|
||||
}
|
||||
|
||||
fun downloadFile(fileUrl: String?, directory: File?, order: Order?) {
|
||||
val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()
|
||||
StrictMode.setThreadPolicy(policy)
|
||||
try {
|
||||
val url = URL(fileUrl)
|
||||
val urlConnection: HttpURLConnection = url.openConnection() as HttpURLConnection
|
||||
urlConnection.connect()
|
||||
val inputStream: InputStream = urlConnection.inputStream
|
||||
val fileOutputStream = FileOutputStream(directory)
|
||||
val buffer = ByteArray(BUFFER_SIZE_SKETCH)
|
||||
var bufferLength = 0
|
||||
while (inputStream.read(buffer).also { bufferLength = it } > 0) {
|
||||
fileOutputStream.write(buffer, 0, bufferLength)
|
||||
}
|
||||
fileOutputStream.close()
|
||||
|
||||
if(order != null){
|
||||
order.sketchPath = directory!!.absolutePath
|
||||
orderBox.put(order)
|
||||
}
|
||||
|
||||
} catch (e: FileNotFoundException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: MalformedURLException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun downloadSketchs(filesDir:String, orders: List<Order>){
|
||||
|
||||
if(!File("$filesDir/pdf_sketchs").isDirectory){
|
||||
Files.createDirectory(Paths.get("$filesDir/pdf_sketchs"))
|
||||
}
|
||||
|
||||
for (order in orders) {
|
||||
if(order.sketchName != null && order.sketchPath == null){
|
||||
downloadFile("${BuildConfig.STORAGE_URL}pdf_croquis/${order.sketchName}", File("$filesDir/pdf_sketchs/${order.sketchName}"), order)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user