fix audit report mismatches across backend and android

This commit is contained in:
2026-04-07 16:06:44 -06:00
parent 0173123898
commit 4500b213c6
22 changed files with 586 additions and 157 deletions

View File

@@ -16,13 +16,11 @@ import retrofit2.http.Query;
public interface InventoryApi {
// GET /api/v1/inventory?q=...&page=...&size=...&category=...&storeId=...&sort=...
@GET("api/v1/inventory")
Call<PageResponse<InventoryDTO>> getAllInventory(
@Query("page") int page,
@Query("size") int size,
@Query("q") String query,
@Query("category") String category,
@Query("storeId") Long storeId,
@Query("sort") String sort);

View File

@@ -3,14 +3,10 @@ package com.example.petstoremobile.api;
import com.example.petstoremobile.dtos.MessageDTO;
import com.example.petstoremobile.dtos.SendMessageRequest;
import java.util.List;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.Path;
//api calls to get and send messages
@@ -21,12 +17,4 @@ public interface MessageApi {
@POST("api/v1/chat/conversations/{id}/messages")
Call<MessageDTO> sendMessage(@Path("id") Long conversationId, @Body SendMessageRequest request);
@Multipart
@POST("api/v1/chat/conversations/{id}/messages/attachment")
Call<MessageDTO> sendMessageWithAttachment(
@Path("id") Long conversationId,
@Part("content") RequestBody content,
@Part MultipartBody.Part file
);
}

View File

@@ -13,7 +13,7 @@ public interface PurchaseOrderApi {
Call<PageResponse<PurchaseOrderDTO>> getAllPurchaseOrders(
@Query("page") int page,
@Query("size") int size,
@Query("query") String query,
@Query("q") String query,
@Query("storeId") Long storeId,
@Query("sort") String sort);

View File

@@ -5,10 +5,8 @@ import com.example.petstoremobile.dtos.SaleDTO;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Path;
import retrofit2.http.Query;
@@ -24,10 +22,4 @@ public interface SaleApi {
@POST("api/v1/sales")
Call<SaleDTO> createSale(@Body SaleDTO sale);
@PUT("api/v1/sales/{id}")
Call<SaleDTO> updateSale(@Path("id") Long id, @Body SaleDTO sale);
@DELETE("api/v1/sales/{id}")
Call<Void> deleteSale(@Path("id") Long id);
}

View File

@@ -1,6 +1,7 @@
package com.example.petstoremobile.api.auth;
import com.example.petstoremobile.dtos.AuthDTO;
import com.example.petstoremobile.dtos.AvatarUploadResponse;
import com.example.petstoremobile.dtos.UserDTO;
import java.util.Map;
@@ -36,7 +37,7 @@ public interface AuthApi {
//upload avatar endpoint
@Multipart
@POST("api/v1/auth/me/avatar")
Call<UserDTO> uploadAvatar(@Part MultipartBody.Part avatar);
Call<AvatarUploadResponse> uploadAvatar(@Part MultipartBody.Part avatar);
//delete avatar endpoint
@DELETE("api/v1/auth/me/avatar")

View File

@@ -0,0 +1,25 @@
package com.example.petstoremobile.dtos;
public class AvatarUploadResponse {
private String avatarUrl;
private String message;
public AvatarUploadResponse() {
}
public String getAvatarUrl() {
return avatarUrl;
}
public void setAvatarUrl(String avatarUrl) {
this.avatarUrl = avatarUrl;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@@ -9,6 +9,7 @@ import android.provider.OpenableColumns;
import android.util.Log;
import android.view.*;
import android.view.inputmethod.EditorInfo;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
@@ -28,21 +29,16 @@ import com.example.petstoremobile.dtos.SendMessageRequest;
import com.example.petstoremobile.models.Chat;
import com.example.petstoremobile.models.Message;
import com.example.petstoremobile.services.ChatNotificationService;
import com.example.petstoremobile.utils.FileUtils;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.viewmodels.ChatViewModel;
import com.example.petstoremobile.websocket.StompChatManager;
import java.io.File;
import java.util.*;
import javax.inject.Inject;
import javax.inject.Named;
import dagger.hilt.android.AndroidEntryPoint;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
@AndroidEntryPoint
public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickListener, StompChatManager.MessageListener,
@@ -361,26 +357,10 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
binding.etMessage.setText("");
removeAttachment();
try {
File file = FileUtils.getFileFromUri(requireContext(), uri);
if (file == null) return;
String mimeType = requireContext().getContentResolver().getType(uri);
RequestBody requestFile = RequestBody.create(file, MediaType.parse(mimeType != null ? mimeType : "application/octet-stream"));
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(), requestFile);
RequestBody contentPart = RequestBody.create(text, MediaType.parse("text/plain"));
viewModel.sendMessageWithAttachment(activeConversationId, contentPart, filePart).observe(getViewLifecycleOwner(), resource -> {
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
messageList.add(dtoToModel(resource.data));
messageAdapter.notifyItemInserted(messageList.size() - 1);
scrollToBottom();
loadConversations();
}
});
} catch (Exception e) {
Log.e(TAG, "Error sending message with attachment", e);
if (!text.isEmpty()) {
binding.etMessage.setText(text);
}
Toast.makeText(requireContext(), "File attachments are not supported", Toast.LENGTH_SHORT).show();
}
/**

View File

@@ -230,9 +230,7 @@ public class ProfileFragment extends Fragment {
viewModel.uploadAvatar(body).observe(getViewLifecycleOwner(), resource -> {
if (resource == null) return;
if (resource.status == Resource.Status.SUCCESS) {
currentUser = resource.data;
Toast.makeText(getContext(), "Avatar updated successfully", Toast.LENGTH_SHORT).show();
// Reload image after successful upload
loadProfileData();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Upload failed: " + resource.message, Toast.LENGTH_SHORT).show();

View File

@@ -210,7 +210,7 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn
}
//Load all inventory items from the backend using viewModel
viewModel.getAllInventory(query, null, storeId, currentPage, PAGE_SIZE, "product.prodName").observe(getViewLifecycleOwner(), resource -> {
viewModel.getAllInventory(query, storeId, currentPage, PAGE_SIZE, "product.prodName").observe(getViewLifecycleOwner(), resource -> {
if (resource == null) return;
// Check the status to see if the resource is loaded and display the data

View File

@@ -7,6 +7,7 @@ import androidx.lifecycle.MutableLiveData;
import com.example.petstoremobile.api.auth.AuthApi;
import com.example.petstoremobile.api.auth.TokenManager;
import com.example.petstoremobile.dtos.AuthDTO;
import com.example.petstoremobile.dtos.AvatarUploadResponse;
import com.example.petstoremobile.dtos.UserDTO;
import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.Resource;
@@ -83,7 +84,7 @@ public class AuthRepository extends BaseRepository {
/**
* Uploads a multipart image to be used as the current user's avatar.
*/
public LiveData<Resource<UserDTO>> uploadAvatar(MultipartBody.Part avatar) {
public LiveData<Resource<AvatarUploadResponse>> uploadAvatar(MultipartBody.Part avatar) {
return executeCall(authApi.uploadAvatar(avatar));
}

View File

@@ -17,9 +17,6 @@ import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
/**
* Repository for handling chat-related data operations.
*/
@@ -58,13 +55,6 @@ public class ChatRepository extends BaseRepository {
return executeCall(messageApi.sendMessage(conversationId, request));
}
/**
* Sends a message with a file attachment to a conversation.
*/
public LiveData<Resource<MessageDTO>> sendMessageWithAttachment(Long conversationId, RequestBody content, MultipartBody.Part file) {
return executeCall(messageApi.sendMessageWithAttachment(conversationId, content, file));
}
/**
* Fetches a paginated list of customers.
*/

View File

@@ -25,8 +25,8 @@ public class InventoryRepository extends BaseRepository {
/**
* Retrieves a paginated list of inventory items from the API with optional search, category, storeId and sort.
*/
public LiveData<Resource<PageResponse<InventoryDTO>>> getAllInventory(String query, String category, Long storeId, int page, int size, String sort) {
return executeCall(inventoryApi.getAllInventory(page, size, query, category, storeId, sort));
public LiveData<Resource<PageResponse<InventoryDTO>>> getAllInventory(String query, Long storeId, int page, int size, String sort) {
return executeCall(inventoryApi.getAllInventory(page, size, query, storeId, sort));
}
/**

View File

@@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModel;
import com.example.petstoremobile.dtos.AuthDTO;
import com.example.petstoremobile.dtos.AvatarUploadResponse;
import com.example.petstoremobile.dtos.UserDTO;
import com.example.petstoremobile.repositories.AuthRepository;
import com.example.petstoremobile.utils.Resource;
@@ -48,7 +49,7 @@ public class AuthViewModel extends ViewModel {
/**
* Uploads a new avatar image for the current user.
*/
public LiveData<Resource<UserDTO>> uploadAvatar(MultipartBody.Part avatar) {
public LiveData<Resource<AvatarUploadResponse>> uploadAvatar(MultipartBody.Part avatar) {
return repository.uploadAvatar(avatar);
}

View File

@@ -16,9 +16,6 @@ import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
/**
* ViewModel for managing chat-related UI state and data operations.
*/
@@ -52,13 +49,6 @@ public class ChatViewModel extends ViewModel {
return repository.sendMessage(conversationId, request);
}
/**
* Sends a message with a file attachment to a conversation.
*/
public LiveData<Resource<MessageDTO>> sendMessageWithAttachment(Long conversationId, RequestBody content, MultipartBody.Part file) {
return repository.sendMessageWithAttachment(conversationId, content, file);
}
/**
* Fetches a paginated list of customers.
*/

View File

@@ -36,8 +36,8 @@ public class InventoryViewModel extends ViewModel {
/**
* Retrieves a paginated list of inventory items, with optional filtering and sorting.
*/
public LiveData<Resource<PageResponse<InventoryDTO>>> getAllInventory(String query, String category, Long storeId, int page, int size, String sort) {
return inventoryRepository.getAllInventory(query, category, storeId, page, size, sort);
public LiveData<Resource<PageResponse<InventoryDTO>>> getAllInventory(String query, Long storeId, int page, int size, String sort) {
return inventoryRepository.getAllInventory(query, storeId, page, size, sort);
}
/**