Commit e1e63f58 authored by Ahmad Abi Mulya's avatar Ahmad Abi Mulya

Merge branch 'dev/background-service' of https://git.mdd.co.id:44195/abimulya/your-cashier

parents e7a1cd85 69df54a4
...@@ -4,6 +4,7 @@ import androidx.appcompat.app.AppCompatActivity; ...@@ -4,6 +4,7 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider; import androidx.core.content.FileProvider;
import androidx.databinding.DataBindingUtil; import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
...@@ -15,21 +16,26 @@ import android.os.Environment; ...@@ -15,21 +16,26 @@ import android.os.Environment;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.example.yourcashiertest.R; import com.example.yourcashiertest.R;
import com.example.yourcashiertest.databinding.ActivityProductBinding; import com.example.yourcashiertest.databinding.ActivityProductBinding;
import com.example.yourcashiertest.entities.Product; import com.example.yourcashiertest.entities.Product;
import com.example.yourcashiertest.services.BackgroundService;
import com.example.yourcashiertest.utils.ViewUtil; import com.example.yourcashiertest.utils.ViewUtil;
import com.example.yourcashiertest.viewmodels.ProductViewModel; import com.example.yourcashiertest.viewmodels.ProductViewModel;
import java.io.File; import java.io.File;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
public class ProductActivity extends AppCompatActivity{
public class ProductActivity extends AppCompatActivity {
private static final int PICK_IMAGE = 123; private static final int PICK_IMAGE = 123;
ActivityProductBinding binding; ActivityProductBinding binding;
private boolean isUpdate = false; private boolean isUpdate = false;
private static final int REQUEST_IMAGE_CAPTURE = 1; private static final int REQUEST_IMAGE_CAPTURE = 1;
private File file; private File file;
private ProductViewModel viewModel; private ProductViewModel viewModel;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
...@@ -41,14 +47,14 @@ public class ProductActivity extends AppCompatActivity{ ...@@ -41,14 +47,14 @@ public class ProductActivity extends AppCompatActivity{
getSupportActionBar().setHomeButtonEnabled(true); getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} }
if (product != null){ if (product != null) {
isUpdate = true; isUpdate = true;
binding.setPhoto(product.getPhoto()); binding.setPhoto(product.getPhoto());
Log.d("Photo", product.getPhoto()); Log.d("Photo", product.getPhoto());
viewModel.setProduct(product); viewModel.setProduct(product);
binding.btnSubmit.setText(R.string.btn_edit); binding.btnSubmit.setText(R.string.btn_edit);
binding.tvHeadProduct.setText("UPDATE PRODUCT"); binding.tvHeadProduct.setText("UPDATE PRODUCT");
}else { } else {
product = new Product("", "", 0, 0, "", ""); product = new Product("", "", 0, 0, "", "");
} }
binding.cvProduct.setOnClickListener(v -> selectAction(this)); binding.cvProduct.setOnClickListener(v -> selectAction(this));
...@@ -59,11 +65,11 @@ public class ProductActivity extends AppCompatActivity{ ...@@ -59,11 +65,11 @@ public class ProductActivity extends AppCompatActivity{
|| TextUtils.isEmpty(binding.etPrice.getText().toString()) || TextUtils.isEmpty(binding.etPrice.getText().toString())
|| TextUtils.isEmpty(binding.etDescription.getText().toString()) || TextUtils.isEmpty(binding.etDescription.getText().toString())
|| TextUtils.isEmpty(binding.etQuantity.getText().toString()) || TextUtils.isEmpty(binding.etQuantity.getText().toString())
|| TextUtils.isEmpty(binding.etCategory.getText().toString())){ || TextUtils.isEmpty(binding.etCategory.getText().toString())) {
ViewUtil.showMessage(binding.getRoot(), getString(R.string.form_error_message)); ViewUtil.showMessage(binding.getRoot(), getString(R.string.form_error_message));
return; return;
} }
if (file != null){ if (file != null) {
fixProduct.setPhoto(file.getAbsolutePath()); fixProduct.setPhoto(file.getAbsolutePath());
} }
fixProduct.setName(binding.etProduct.getText().toString()); fixProduct.setName(binding.etProduct.getText().toString());
...@@ -71,15 +77,16 @@ public class ProductActivity extends AppCompatActivity{ ...@@ -71,15 +77,16 @@ public class ProductActivity extends AppCompatActivity{
fixProduct.setDescription(binding.etDescription.getText().toString()); fixProduct.setDescription(binding.etDescription.getText().toString());
fixProduct.setPrice(Long.parseLong(TextUtils. fixProduct.setPrice(Long.parseLong(TextUtils.
isEmpty(binding.etPrice.getText().toString()) ? "0" : binding.etPrice.getText().toString())); isEmpty(binding.etPrice.getText().toString()) ? "0" : binding.etPrice.getText().toString()));
fixProduct.setQuantity(Long.parseLong(TextUtils. fixProduct.setQuantity(Long.parseLong(TextUtils.
isEmpty(binding.etQuantity.getText().toString()) ? "0" : binding.etQuantity.getText().toString())); isEmpty(binding.etQuantity.getText().toString()) ? "0" : binding.etQuantity.getText().toString()));
if (isUpdate){ if (isUpdate) {
viewModel.updateProduct(fixProduct); viewModel.updateProduct(fixProduct);
}else { } else {
viewModel.insertProduct(fixProduct); viewModel.insertProduct(fixProduct);
BackgroundService.startActionPushProduct(this);
} }
finish(); finish();
}catch (Exception e){ } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
startActivity(new Intent(ProductActivity.this, MainActivity.class)); startActivity(new Intent(ProductActivity.this, MainActivity.class));
...@@ -100,8 +107,9 @@ public class ProductActivity extends AppCompatActivity{ ...@@ -100,8 +107,9 @@ public class ProductActivity extends AppCompatActivity{
} }
} }
} }
private void selectAction(Context context){
final CharSequence[] options = { "Take Photo", "Choose from Gallery","Cancel" }; private void selectAction(Context context) {
final CharSequence[] options = {"Take Photo", "Choose from Gallery", "Cancel"};
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Choose your profile picture"); builder.setTitle("Choose your profile picture");
builder.setItems(options, new DialogInterface.OnClickListener() { builder.setItems(options, new DialogInterface.OnClickListener() {
...@@ -118,11 +126,13 @@ public class ProductActivity extends AppCompatActivity{ ...@@ -118,11 +126,13 @@ public class ProductActivity extends AppCompatActivity{
}); });
builder.show(); builder.show();
} }
private void openGallery(){
private void openGallery() {
Intent intent = new Intent(Intent.ACTION_PICK); Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*"); intent.setType("image/*");
startActivityForResult(intent, PICK_IMAGE); startActivityForResult(intent, PICK_IMAGE);
} }
private File createImageFile() { private File createImageFile() {
try { try {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
...@@ -138,37 +148,39 @@ public class ProductActivity extends AppCompatActivity{ ...@@ -138,37 +148,39 @@ public class ProductActivity extends AppCompatActivity{
return null; return null;
} }
} }
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
Uri imageUri; Uri imageUri;
if (resultCode == RESULT_OK && requestCode == PICK_IMAGE ){ if (resultCode == RESULT_OK && requestCode == PICK_IMAGE) {
//set image to image view //set image to image view
// binding.ivProduct.setImageURI(data.getData()); // binding.ivProduct.setImageURI(data.getData());
imageUri = data.getData(); imageUri = data.getData();
if (imageUri != null){ if (imageUri != null) {
file = new File(getPath(imageUri)); file = new File(getPath(imageUri));
} else { } else {
file = file.getAbsoluteFile(); file = file.getAbsoluteFile();
} }
Log.d("testPhoto", ""+ file.getAbsolutePath()); Log.d("testPhoto", "" + file.getAbsolutePath());
binding.setPhoto(file.getAbsolutePath()); binding.setPhoto(file.getAbsolutePath());
}else if(requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { } else if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Log.d("photo", ""+ requestCode); Log.d("photo", "" + requestCode);
binding.setPhoto(file.getAbsolutePath()); binding.setPhoto(file.getAbsolutePath());
} }
} }
public String getPath(Uri uri)
{ public String getPath(Uri uri) {
String[] projection = { MediaStore.Images.Media.DATA }; String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(uri, projection, null, null, null); Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
if (cursor == null) return null; if (cursor == null) return null;
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst(); cursor.moveToFirst();
String s=cursor.getString(column_index); String s = cursor.getString(column_index);
cursor.close(); cursor.close();
return s; return s;
} }
@Override @Override
public boolean onSupportNavigateUp() { public boolean onSupportNavigateUp() {
onBackPressed(); onBackPressed();
......
package com.example.yourcashiertest.models;
import com.example.yourcashiertest.entities.Product;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
public class PushProduct {
@SerializedName("name")
private String name;
@SerializedName("price")
private int price;
@SerializedName("stock")
private int stock;
@SerializedName("description")
private String description;
@SerializedName("category")
private String category;
@SerializedName("images")
private String images;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getStock() {
return stock;
}
public void setStock(int stock) {
this.stock = stock;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getImages() {
return images;
}
public void setImages(String images) {
this.images = images;
}
@Override
public String toString() {
return new Gson().toJson(this);
}
public static PushProduct from(Product product) {
PushProduct pushProduct = new PushProduct();
pushProduct.name = product.getName();
pushProduct.category = product.getCategory();
pushProduct.description = product.getDescription();
pushProduct.images = product.getPhoto();
pushProduct.price = (int) product.getPrice();
pushProduct.stock = (int) product.getQuantity();
return pushProduct;
}
}
\ No newline at end of file
package com.example.yourcashiertest.models;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class PushProductResponse {
@SerializedName("status")
@Expose
private Boolean status;
@SerializedName("messages")
@Expose
private String messages;
@SerializedName("data")
@Expose
private Data data;
public Boolean getStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public String getMessages() {
return messages;
}
public void setMessages(String messages) {
this.messages = messages;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public class Data {
@SerializedName("name")
@Expose
private String name;
@SerializedName("price")
@Expose
private Integer price;
@SerializedName("description")
@Expose
private String description;
@SerializedName("category")
@Expose
private String category;
@SerializedName("stock")
@Expose
private Integer stock;
@SerializedName("images")
@Expose
private String images;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public Integer getStock() {
return stock;
}
public void setStock(Integer stock) {
this.stock = stock;
}
public String getImages() {
return images;
}
public void setImages(String images) {
this.images = images;
}
}
}
package com.example.yourcashiertest.services;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.core.app.JobIntentService;
import com.example.yourcashiertest.clients.ApiClient;
import com.example.yourcashiertest.daos.ProductDao;
import com.example.yourcashiertest.databases.LocalDatabase;
import com.example.yourcashiertest.entities.Product;
import com.example.yourcashiertest.models.PushProduct;
import com.example.yourcashiertest.models.User;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class BackgroundService extends JobIntentService {
public static final String BASE_URL = "https://your-cashier.herokuapp.com/api/";
private static final String ACTION_PUSH_PRODUCT = "com.example.yourcashiertest.services.action.PUSH_PRODUCT";
public BackgroundService() {
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_PUSH_PRODUCT.equals(action)) {
handlePushProduct();
}
}
}
private void handlePushProduct() {
LocalDatabase localDatabase = LocalDatabase.getDatabase(this);
ProductDao productDao = localDatabase.productDao();
List<Product> productList = productDao.getAll();
for (Product product : productList) {
PushProduct pushProduct = PushProduct.from(product);
ApiClient.client(ProductService.class, BASE_URL).createProduct(pushProduct)
.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
}
@Override
public void onFailure(Call<User> call, Throwable t) {
}
});
}
}
public static synchronized void startActionPushProduct(Context context) {
Intent intent = new Intent(context, BackgroundService.class);
intent.setAction(ACTION_PUSH_PRODUCT);
context.startService(intent);
}
}
package com.example.yourcashiertest.services;
import com.example.yourcashiertest.models.PushProduct;
import com.example.yourcashiertest.models.PushProductResponse;
import com.example.yourcashiertest.models.ResponseLogin;
import com.example.yourcashiertest.models.ResponseUser;
import com.example.yourcashiertest.models.User;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.POST;
import retrofit2.http.PUT;
public interface ProductService {
@GET("v1/product")
Call<String> getProduct();
@Headers("Content-Type: application/json")
@POST("v1/product")
Call<PushProductResponse> createProduct(@Body PushProduct pushProduct);
@Headers("Content-Type: application/json")
@PUT("v1/product/{id}")
Call<PushProductResponse> updateProduct(@Body PushProduct pushProduct);
}
...@@ -122,7 +122,7 @@ ...@@ -122,7 +122,7 @@
app:layout_constraintTop_toBottomOf="@+id/tv_user" app:layout_constraintTop_toBottomOf="@+id/tv_user"
app:layout_constraintVertical_bias="0.48000002" app:layout_constraintVertical_bias="0.48000002"
tools:layout_editor_absoluteX="16dp" tools:layout_editor_absoluteX="16dp"
android:hint="Cari product ... " android:hint="Cari pushProduct ... "
android:imeOptions="actionSearch" android:imeOptions="actionSearch"
android:inputType="textCapWords" android:inputType="textCapWords"
android:textSize="@dimen/text_default" /> android:textSize="@dimen/text_default" />
......
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Product Name" android:hint="Product Name"
android:text="@{viewModel.product.name}" android:text="@{viewModel.pushProduct.name}"
android:inputType="textCapWords" android:inputType="textCapWords"
android:textSize="@dimen/text_default" /> android:textSize="@dimen/text_default" />
...@@ -86,7 +86,7 @@ ...@@ -86,7 +86,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Price" android:hint="Price"
android:text="@{viewModel.product.price == 0 ? `` : viewModel.product.price + ``}" android:text="@{viewModel.pushProduct.price == 0 ? `` : viewModel.pushProduct.price + ``}"
android:inputType="number" android:inputType="number"
android:textSize="@dimen/text_default" /> android:textSize="@dimen/text_default" />
...@@ -108,7 +108,7 @@ ...@@ -108,7 +108,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="Qty" android:hint="Qty"
android:text="@{viewModel.product.quantity == 0 ? `` : viewModel.product.quantity + ``}" android:text="@{viewModel.pushProduct.quantity == 0 ? `` : viewModel.pushProduct.quantity + ``}"
android:inputType="number" android:inputType="number"
android:textSize="@dimen/text_default" /> android:textSize="@dimen/text_default" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
...@@ -125,7 +125,7 @@ ...@@ -125,7 +125,7 @@
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/etCategory" android:id="@+id/etCategory"
android:hint="Category" android:hint="Category"
android:text="@{viewModel.product.category}" android:text="@{viewModel.pushProduct.category}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
...@@ -148,7 +148,7 @@ ...@@ -148,7 +148,7 @@
android:inputType="textMultiLine" android:inputType="textMultiLine"
android:lines="3" android:lines="3"
android:maxLines="3" android:maxLines="3"
android:text="@{viewModel.product.description}" android:text="@{viewModel.pushProduct.description}"
android:textSize="@dimen/text_default" /> android:textSize="@dimen/text_default" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<data> <data>
<import type="android.view.View"/> <import type="android.view.View"/>
<variable <variable
name="product" name="pushProduct"
type="com.example.yourcashiertest.entities.Product" /> type="com.example.yourcashiertest.entities.Product" />
<variable <variable
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
android:layout_height="130dp" android:layout_height="130dp"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:scaleType="fitXY" android:scaleType="fitXY"
app:file="@{product.photo}" app:file="@{pushProduct.photo}"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.8" app:layout_constraintHorizontal_bias="0.8"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
android:id="@+id/tv_name" android:id="@+id/tv_name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{product.name}" android:text="@{pushProduct.name}"
android:textStyle="bold" android:textStyle="bold"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:maxLength="20" android:maxLength="20"
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
android:id="@+id/tv_desc" android:id="@+id/tv_desc"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{product.description}" android:text="@{pushProduct.description}"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="@dimen/space_default" android:layout_marginBottom="@dimen/space_default"
android:maxLength="40" android:maxLength="40"
...@@ -148,7 +148,7 @@ ...@@ -148,7 +148,7 @@
android:layout_height="20sp" android:layout_height="20sp"
android:textColor="@color/white" android:textColor="@color/white"
android:textAlignment="center" android:textAlignment="center"
android:text="@{product.quantity + ``}" android:text="@{pushProduct.quantity + ``}"
android:background="@drawable/ic_stok" android:background="@drawable/ic_stok"
app:layout_constraintBottom_toBottomOf="@+id/tvStock" app:layout_constraintBottom_toBottomOf="@+id/tvStock"
app:layout_constraintTop_toTopOf="@+id/tvStock" app:layout_constraintTop_toTopOf="@+id/tvStock"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment