Add audit date in inspection report

main
saad.siddiq 2025-05-06 14:35:50 +05:00
parent fdf6b32e79
commit 8d6aef0228
11 changed files with 279 additions and 26 deletions

View File

@ -10,8 +10,8 @@ android {
applicationId "com.utopiaindustries.qualitychecker"
minSdk 24
targetSdk 34
versionCode 3
versionName "1.2"
versionCode 5
versionName "1.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

View File

@ -61,17 +61,17 @@
</intent-filter>
</activity>
<service
<!--<service
android:name=".service.NetworkService"
android:exported="false" />
android:exported="false" />-->
<receiver
<!--<receiver
android:name=".receiver.NetworkReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</receiver>-->
<provider
android:name="androidx.core.content.FileProvider"

View File

@ -20,7 +20,7 @@ import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitClient {
private final static String BASE_URL = "https://portal.utopiaindustries.pk/uind/";
//private final static String BASE_URL = "http://192.168.91.44:8080/uind/";//"http://192.168.91.44:8081/uind/";//"http://192.168.90.27:8080/uind/";//"http://192.168.91.16:8080/uind/";
//private final static String BASE_URL = "http://192.168.91.44:8081/uind/";//"http://192.168.91.44:8081/uind/";//"http://192.168.90.27:8080/uind/";//"http://192.168.91.16:8080/uind/";
private static Retrofit retrofit;

View File

@ -8,6 +8,7 @@ import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.utopiaindustries.qualitychecker.models.InspectionReportWrapper;
@ -40,6 +41,7 @@ public class ReportRepository {
}
public void insert(InspectionReportWrapper wrapper) {
Log.e("insert: ","*********"+wrapper.getId());
executeSafely(() -> {
openDatabase();
database.beginTransaction();
@ -49,6 +51,14 @@ public class ReportRepository {
values.put(DatabaseHelper.REPORT_COLUMN_SYNCED, wrapper.isSynced());
database.insertWithOnConflict(DatabaseHelper.REPORT_TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE);
database.setTransactionSuccessful();
// Count total rows after insert
/*Cursor cursor = database.rawQuery("SELECT COUNT(*) FROM " + DatabaseHelper.REPORT_TABLE_NAME, null);
if (cursor != null && cursor.moveToFirst()) {
int count = cursor.getInt(0);
Log.e("Total Rows Inserted", String.valueOf(count));
cursor.close();
}*/
} catch (Exception e) {
e.printStackTrace();
} finally {
@ -58,6 +68,29 @@ public class ReportRepository {
});
}
public List<String> getAllSavedPaths() {
List<String> paths = new ArrayList<>();
openDatabase();
Cursor cursor = null;
try {
cursor = database.query(
DatabaseHelper.REPORT_TABLE_NAME,
new String[]{DatabaseHelper.REPORT_COLUMN_CONTENT},
null, null, null, null, null
);
if (cursor != null && cursor.moveToFirst()) {
do {
paths.add(cursor.getString(0));
} while (cursor.moveToNext());
}
} finally {
if (cursor != null) cursor.close();
close();
}
return paths;
}
public void insertOrReplaceUser(InspectionReportWrapper wrapper) {
executeSafely(() -> {
openDatabase();

View File

@ -3,6 +3,7 @@ package com.utopiaindustries.qualitychecker.models;
import androidx.annotation.NonNull;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.List;
public class InspectionReport implements Serializable {
@ -23,6 +24,7 @@ public class InspectionReport implements Serializable {
private String productionRepresentative;
private String qcRepresentative;
private String floor;
private String auditDate;
// wrapper
@ -179,7 +181,13 @@ public class InspectionReport implements Serializable {
this.filePath = filePath;
}
public String getAuditDate() {
return auditDate;
}
public void setAuditDate(String auditDate) {
this.auditDate = auditDate;
}
@Override
public String toString() {
@ -201,6 +209,7 @@ public class InspectionReport implements Serializable {
", floor='" + floor + '\'' +
", items=" + items +
", filePath='" + filePath + '\'' +
", auditDate='" + auditDate + '\'' +
", wrapperId=" + wrapperId +
'}';
}

View File

@ -43,17 +43,21 @@ import com.utopiaindustries.qualitychecker.db.InspectionCheckpointSkuRepository;
import com.utopiaindustries.qualitychecker.db.InspectionLabelRepository;
import com.utopiaindustries.qualitychecker.db.ItemRepository;
import com.utopiaindustries.qualitychecker.db.ProductRepository;
import com.utopiaindustries.qualitychecker.db.ReportRepository;
import com.utopiaindustries.qualitychecker.models.EmployeePhoto;
import com.utopiaindustries.qualitychecker.models.InspectionReport;
import com.utopiaindustries.qualitychecker.models.InspectionReportWrapper;
import com.utopiaindustries.qualitychecker.models.callback.SaveCheckpointCallback;
import com.utopiaindustries.qualitychecker.models.callback.SaveDefectCallback;
import com.utopiaindustries.qualitychecker.models.callback.SaveDimensionCallback;
import com.utopiaindustries.qualitychecker.models.callback.SaveInspectionLabelCallBack;
import com.utopiaindustries.qualitychecker.models.callback.SaveItemCallback;
import com.utopiaindustries.qualitychecker.models.callback.SaveProductCallBack;
import com.utopiaindustries.qualitychecker.models.callback.SaveReportCallback;
import com.utopiaindustries.qualitychecker.notification.NotificationHelper;
import com.utopiaindustries.qualitychecker.receiver.NetworkReceiver;
import com.utopiaindustries.qualitychecker.service.InspectionReportService;
import com.utopiaindustries.qualitychecker.service.NetworkService;
import com.utopiaindustries.qualitychecker.store.Store;
import com.utopiaindustries.qualitychecker.ui.activities.fragments.ReportsFragment;
import com.utopiaindustries.qualitychecker.ui.adapter.PagerAdapter;
@ -63,6 +67,9 @@ import com.utopiaindustries.qualitychecker.utils.FileUtils;
import com.utopiaindustries.qualitychecker.utils.PropertyReader;
import com.utopiaindustries.qualitychecker.utils.Release;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
@ -73,7 +80,7 @@ import retrofit2.Response;
public class HomeActivity extends AppCompatActivity implements View.OnClickListener {
private Button createReportBtn,refreshReportsBtn,logoutBtn,fetchProductBtn, appUpdateBtn;
private Button createReportBtn,refreshReportsBtn,logoutBtn,fetchProductBtn, appUpdateBtn, reportsUploadBtn;
//private RecyclerView recyclerView;
private ApiService apiService;
private TextView usernameTitle;//, emptyReportTextView;
@ -115,6 +122,7 @@ public class HomeActivity extends AppCompatActivity implements View.OnClickListe
logoutBtn = findViewById( R.id.logout_btn );
fetchProductBtn = findViewById( R.id.fetch_product_btn );
appUpdateBtn = findViewById(R.id.app_update_btn);
reportsUploadBtn = findViewById(R.id.reports_upload_btn);
progressBar = findViewById(R.id.progressBar);
//recyclerView = findViewById( R.id.reports_recyclerview );
usernameTitle = findViewById( R.id.username_title );
@ -138,6 +146,7 @@ public class HomeActivity extends AppCompatActivity implements View.OnClickListe
logoutBtn.setOnClickListener( this );
fetchProductBtn.setOnClickListener( this );
appUpdateBtn.setOnClickListener( this );
reportsUploadBtn.setOnClickListener( this );
//recyclerView.setLayoutManager( new LinearLayoutManager( this ) );
@ -228,6 +237,17 @@ public class HomeActivity extends AppCompatActivity implements View.OnClickListe
}
}
if ( id == R.id.reports_upload_btn) {
if (!FileUtils.isNetworkConnected(this)) {
Toast.makeText(this, "No Internet Connection Available", Toast.LENGTH_LONG).show();
}
else {
pushDataToInternet();
}
}
}
private int generateRandomNumber(int min, int max) {
@ -480,21 +500,21 @@ private int generateRandomNumber(int min, int max) {
@Override
protected void onStart() {
super.onStart();
if (networkReceiver == null) {
/*if (networkReceiver == null) {
networkReceiver = new NetworkReceiver();
}
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(networkReceiver, filter);
isReceiverRegistered = true; // Mark the receiver as registered
isReceiverRegistered = true; */ // Mark the receiver as registered
}
@Override
protected void onStop() {
super.onStop();
if (isReceiverRegistered) {
/*if (isReceiverRegistered) {
unregisterReceiver(networkReceiver);
isReceiverRegistered = false; // Mark the receiver as unregistered
}
}*/
}
/**
@ -555,4 +575,90 @@ private int generateRandomNumber(int min, int max) {
}
} );
}
@SuppressLint("DefaultLocale")
private void pushDataToInternet() {
ReportRepository repository = new ReportRepository( this );
List<InspectionReportWrapper> reportWrappers = repository.findAllUnsynced();
InspectionReportService service = InspectionReportService.getInstance();
try {
List<InspectionReport> reports = getReports( reportWrappers );
int size = reports.size();
if( size > 0 ) {
Toast.makeText(this, "Uploading Reports. Please wait", Toast.LENGTH_LONG).show();
reportsUploadBtn.setEnabled(false);
final int[] uploadedCount = {0};
for ( InspectionReport report : reports ){
service.saveReport(report, new SaveReportCallback() {
@Override
public void onSuccess() {
// update status
repository.updateSyncStatus( report.getWrapperId() );
// remove file
FileUtils.deleteFile( report.getFilePath() );
uploadedCount[0]++;
NotificationHelper.showNotification(
HomeActivity.this,
"Report Uploading",
"Uploaded " + uploadedCount[0] + " of " + size + " reports");
//Log.e("Reports-size: ",""+reports.size());
if (uploadedCount[0] == size) {
Toast.makeText(HomeActivity.this, "All reports uploaded successfully", Toast.LENGTH_SHORT).show();
reportsUploadBtn.setEnabled(true);
}
}
@Override
public void onFailure(Throwable throwable) {
uploadedCount[0]++;
// Even on failure, increment the counter to avoid locking the button forever
NotificationHelper.showNotification(
HomeActivity.this,
"Report Uploading",
"Uploaded " + uploadedCount[0] + " of " + size + " reports (with some errors)");
if (uploadedCount[0] == size) {
reportsUploadBtn.setEnabled(true);
Toast.makeText(HomeActivity.this, "Finished uploading with some errors", Toast.LENGTH_SHORT).show();
}
}
});
}
}
else {
Toast.makeText(this, "No Reports to upload", Toast.LENGTH_SHORT).show();
}
} catch ( Exception e ) {
e.printStackTrace();
}
}
/*
* map wrapper to reports
* */
private List<InspectionReport> getReports(List<InspectionReportWrapper> wrappers ) {
List<InspectionReport> reports = new ArrayList<>();
if( ! wrappers.isEmpty() ){
for( InspectionReportWrapper wrapper : wrappers ){
try {
// get file from path
byte[] result = FileUtils.readFile( wrapper.getContent() );
ByteArrayInputStream byteIn = new ByteArrayInputStream( result );
ObjectInputStream in = new ObjectInputStream(byteIn);
InspectionReport report = ( InspectionReport ) in.readObject();
report.setWrapperId( wrapper.getId() );
report.setFilePath( wrapper.getContent() );
reports.add( report );
} catch (Exception | OutOfMemoryError e){
e.printStackTrace();
}
}
}
return reports;
}
}

View File

@ -5,6 +5,7 @@ import static android.app.Activity.RESULT_OK;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@ -25,6 +26,7 @@ import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
@ -67,9 +69,13 @@ import com.utopiaindustries.qualitychecker.utils.FileUtils;
import com.utopiaindustries.qualitychecker.utils.ImageUriHolder;
import java.io.File;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
@ -104,6 +110,11 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener
ArrayList<String> sectionArrayList = new ArrayList<>();
private EditText etHandFeelNotOk, etHandFeelOk, etHandFeelPercent;
private ImageView imgCalendar;
private TextView txtDate;
private int year, month, day;
private Calendar calendar;
private LocalDate localDate;
@Nullable
@Override
@ -302,9 +313,36 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener
}
});
imgCalendar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showDatePickerDialog(getActivity());
}
});
return view;
}
private void showDatePickerDialog(Context context) {
DatePickerDialog datePickerDialog = new DatePickerDialog(
context,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
// Month is 0-indexed, so we add 1
Calendar selectedCalendar = Calendar.getInstance();
selectedCalendar.set(year, monthOfYear, dayOfMonth);
SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy", Locale.getDefault());
String selectedDate = dateFormat.format(selectedCalendar.getTime());
txtDate.setText(selectedDate);
store.getReport().setAuditDate(selectedDate);
}
},
year, month, day
);
datePickerDialog.show();
}
public void onImagePickerResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST) {
Uri selectedImageUri = ImageUriHolder.getInstance().getImageUri();
@ -633,6 +671,7 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener
sectionSpinner.setSelection(index);
etHandFeelNotOk.setText(String.valueOf(store.getReport().getItems().get(0).getHandFeelNotOkay()));
txtDate.setText(store.getReport().getAuditDate());
}
}
@ -714,6 +753,14 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener
txtMinor = view.findViewById(R.id.txt_minor);
etFloor = view.findViewById(R.id.et_floor);
calendar = Calendar.getInstance();
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH);
day = calendar.get(Calendar.DAY_OF_MONTH);
imgCalendar = view.findViewById(R.id.img_calendar);
txtDate = view.findViewById(R.id.txt_date);
etHandFeelNotOk = view.findViewById(R.id.et_hand_feel_not_ok);
etHandFeelOk = view.findViewById(R.id.et_hand_feel_ok);
etHandFeelPercent = view.findViewById(R.id.et_not_ok_percent);

View File

@ -207,6 +207,20 @@ public class FileUtils {
}).start();
}
public static byte[] readFileToByteArray(String path) throws IOException {
File file = new File(path);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
fis.close();
return bos.toByteArray();
}
/**
* is null or empty
*/

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#808080" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M19,4h-1V2h-2v2H8V2H6v2H5C3.89,4 3.01,4.9 3.01,6L3,20c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V6C21,4.9 20.1,4 19,4zM19,20H5V10h14V20zM9,14H7v-2h2V14zM13,14h-2v-2h2V14zM17,14h-2v-2h2V14zM9,18H7v-2h2V18zM13,18h-2v-2h2V18zM17,18h-2v-2h2V18z"/>
</vector>

View File

@ -90,10 +90,10 @@
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
android:layout_below="@+id/layout_heading"
app:tabGravity="fill"
app:tabMode="fixed"
android:layout_below="@+id/layout_heading" />
app:tabMaxWidth="0dp"
app:tabMode="fixed" />
<com.utopiaindustries.qualitychecker.utils.NonSwipeableViewPager
android:id="@+id/viewpager"
@ -129,6 +129,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="#F5F5F5"
app:layout_constraintVertical_bias="1.0">
<Button
@ -178,6 +179,15 @@
android:layout_toStartOf="@id/fetch_product_btn"
android:text="App Update" />
<Button
android:id="@+id/reports_upload_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/app_update_btn"
android:layout_marginEnd="16dp"
android:layout_toStartOf="@id/app_update_btn"
android:text="Upload Reports" />
</RelativeLayout>
<ProgressBar

View File

@ -742,17 +742,46 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_weight="1"
android:text="Vocs"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_weight="1"
android:text="Vocs"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/txt_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/img_calendar"
android:layout_marginStart="5dp"
android:layout_marginTop="5dp"
android:gravity="left"
android:hint="MM-dd-yyyy"
android:padding="5dp"
android:textColor="@color/black" />
<ImageView
android:id="@+id/img_calendar"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="10dp"
android:src="@drawable/icon_calendar" />
</RelativeLayout>
<!-- <Spinner-->
<!-- android:id="@+id/result_spinner"-->
<!-- android:layout_width="wrap_content"-->