com.app_software.chromisstock.ProductDetailFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.app_software.chromisstock.ProductDetailFragment.java

Source

//    ChromisStock
//    Copyright (c) 2015 John Barrett
//    http://www.app-software.com
//    http://www.chromis.co.uk
//
//    This file is part of Chromis Stock
//    An Android based system that works with Chromis POS and some versions of Unicenta POS
//
//    ChromisStock is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    ChromisStock does not include the changes uploader. This is a seperate, bolt on application
//    that can be downloaded from Google Play.
//
//    ChromisStock is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with Chromis POS.

package com.app_software.chromisstock;

import android.app.Activity;
import android.app.SearchManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;

import com.app_software.chromisstock.Data.StockProduct;
import com.google.zxing.integration.android.ScannerIntegrator;
import com.google.zxing.integration.android.ScannerResult;

import java.io.ByteArrayOutputStream;
import java.util.List;

/**
 * A fragment representing a single Product detail screen.
 * This fragment is either contained in a {@link ProductListActivity}
 * in two-pane mode (on tablets) or a {@link ProductDetailActivity}
 * on handsets.
 */
public class ProductDetailFragment extends Fragment implements DatabaseHandler.DataChangeNotify {
    static final String TAG = "ProductDetailFragment";

    static final int REQUEST_IMAGE_CAPTURE = 1;

    public static final String ARG_ITEM_ID = StockProduct.ID;

    /**
     * The content this fragment is presenting.
     */
    private StockProduct mItem;
    private String m_LastTaxCat;
    private String m_LastCategory;
    private DatabaseHandler m_db;
    private Spinner m_taxSpinner;
    private Spinner m_categorySpinner;
    private ImageView m_image;
    private TextView m_txt_location;

    private EditText m_edit_name;
    private EditText m_edit_reference;
    private EditText m_edit_barcode;
    private EditText m_edit_instock;
    private EditText m_edit_minqty;
    private EditText m_edit_maxqty;
    private EditText m_edit_pricebuy;
    private EditText m_edit_pricesell;

    private TaxCatAdapter m_taxAdaptor;
    private CategoryAdapter m_categoryAdaptor;

    private boolean m_nameChecked = false;

    /**
     * Mandatory empty constructor for the fragment manager to instantiate the
     * fragment (e.g. upon screen orientation changes).
     */
    public ProductDetailFragment() {
    }

    public void setDatabase(DatabaseHandler db) {
        m_db = db;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getArguments().containsKey(ARG_ITEM_ID)) {
            if (m_db == null) {
                m_db = DatabaseHandler.getInstance(getActivity());
            }

            Long id = getArguments().getLong(ARG_ITEM_ID);

            mItem = m_db.getProduct(id, true);
        }

        // We are interested in database changes
        DatabaseHandler db = DatabaseHandler.getInstance(getActivity());
        db.addChangeNotify(this);
    }

    @Override
    public void onDestroy() {
        // No longer interested in database changes
        DatabaseHandler db = DatabaseHandler.getInstance(getActivity());
        db.removeChangeNotify(this);

        super.onDestroy();
    }

    @Override
    public void NotifyDataChanged(int action, String chromisID) {
        switch (action) {
        case DatabaseHandler.CHANGENOTIFY_RESET:
            // Best to die
            getActivity().finish();
            break;
        case DatabaseHandler.CHANGENOTIFY_CHANGEPRODUCT:
            if (mItem.getChromisId().compareTo(chromisID) == 0) {
                // Refetch our data
                mItem = m_db.getProduct(chromisID, true);
                setViewsContent();
            }
            break;
        case DatabaseHandler.CHANGENOTIFY_DELETPRODUCT:
            if (mItem.getChromisId().compareTo(chromisID) == 0) {
                getActivity().finish();
            }
            break;
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_product_detail, container, false);

        m_taxSpinner = ((Spinner) rootView.findViewById(R.id.spn_taxcat));
        m_categorySpinner = ((Spinner) rootView.findViewById(R.id.spn_category));
        m_image = (ImageView) rootView.findViewById(R.id.iv_image);
        m_image.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        m_txt_location = (TextView) rootView.findViewById(R.id.txt_location);

        m_edit_name = (EditText) rootView.findViewById(R.id.edit_name);
        m_edit_reference = (EditText) rootView.findViewById(R.id.edit_reference);
        m_edit_barcode = (EditText) rootView.findViewById(R.id.edit_barcode);
        m_edit_instock = (EditText) rootView.findViewById(R.id.edit_instock);
        m_edit_minqty = (EditText) rootView.findViewById(R.id.edit_minqty);
        m_edit_maxqty = (EditText) rootView.findViewById(R.id.edit_maxqty);
        m_edit_pricebuy = (EditText) rootView.findViewById(R.id.edit_pricebuy);
        m_edit_pricesell = (EditText) rootView.findViewById(R.id.edit_pricesell);

        m_taxAdaptor = new TaxCatAdapter(m_db.getTaxCats());
        m_taxSpinner.setAdapter(m_taxAdaptor);
        m_taxSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                DatabaseHandler.TaxCat item = (DatabaseHandler.TaxCat) arg0.getItemAtPosition(arg2);
                if (item != null) {
                    if (TextUtils.isEmpty(m_LastTaxCat) || m_LastTaxCat.compareTo(item.ChromisId) != 0) {
                        m_db.addChange(mItem.getChromisId(), DatabaseHandler.CHANGETYPE_CHANGEVALUE,
                                StockProduct.TAXCAT, item.ChromisId, item.Name);
                        m_LastTaxCat = item.ChromisId;
                    }
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
            }
        });

        m_categoryAdaptor = new CategoryAdapter(m_db.getCategories());
        m_categorySpinner.setAdapter(m_categoryAdaptor);
        m_categorySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                DatabaseHandler.Category item = (DatabaseHandler.Category) arg0.getItemAtPosition(arg2);
                if (item != null) {
                    if (TextUtils.isEmpty(m_LastCategory) || m_LastCategory.compareTo(item.ChromisId) != 0) {
                        m_db.addChange(mItem.getChromisId(), DatabaseHandler.CHANGETYPE_CHANGEVALUE,
                                StockProduct.CATEGORY, item.ChromisId, item.Name);
                        m_LastCategory = item.ChromisId;
                    }
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
            }
        });

        m_image.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                dispatchTakePictureIntent();
            }
        });

        rootView.findViewById(R.id.ibAddStock).setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onEditItem(v);
            }
        });

        rootView.findViewById(R.id.ibBarcode).setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onScanItem(v);
            }
        });

        m_edit_instock.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onEditItem(v);
            }
        });
        rootView.findViewById(R.id.edit_name).setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onEditItem(v);
            }
        });
        m_edit_reference.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onEditItem(v);
            }
        });
        m_edit_barcode.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onEditItem(v);
            }
        });
        m_edit_minqty.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onEditItem(v);
            }
        });
        m_edit_maxqty.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onEditItem(v);
            }
        });
        m_edit_pricebuy.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onEditItem(v);
            }
        });
        m_edit_pricesell.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onEditItem(v);
            }
        });

        setViewsContent();

        return rootView;
    }

    private void setViewsContent() {

        if (mItem != null) {
            m_edit_name.setText(mItem.getValueString(StockProduct.NAME));
            m_edit_reference.setText(mItem.getValueString(StockProduct.REFERENCE));
            m_edit_barcode.setText(mItem.getValueString(StockProduct.CODE));
            m_edit_instock.setText(String.format("%.0f", mItem.getValueDouble(StockProduct.QTY_INSTOCK)));
            m_edit_minqty.setText(String.format("%.0f", mItem.getValueDouble(StockProduct.QTY_MIN)));
            m_edit_maxqty.setText(String.format("%.0f", mItem.getValueDouble(StockProduct.QTY_MAX)));
            m_edit_pricebuy.setText(String.format("%.2f", mItem.getValueDouble(StockProduct.PRICEBUY)));
            m_edit_pricesell.setText(String.format("%.2f", mItem.getValueDouble(StockProduct.PRICESELL)));

            DatabaseHandler.Location loc = m_db.getLocation(mItem.getValueString(StockProduct.LOCATION));
            if (loc != null) {
                m_txt_location.setText(loc.Name);
            }

            m_LastTaxCat = mItem.getValueString(StockProduct.TAXCAT);
            m_taxSpinner.setSelection(m_taxAdaptor.getPosition((m_LastTaxCat)));

            m_LastCategory = mItem.getValueString(StockProduct.CATEGORY);
            m_categorySpinner.setSelection(m_categoryAdaptor.getPosition((m_LastCategory)));

            byte[] image = mItem.getValueByteArray(StockProduct.IMAGE);
            if (image != null) {
                Bitmap bmp = BitmapFactory.decodeByteArray(image, 0, image.length);
                m_image.setImageBitmap(bmp);
            }

            // Force entry of name field
            if (!m_nameChecked && TextUtils.isEmpty(mItem.getValueString(StockProduct.NAME))) {
                m_nameChecked = true;
                onEditItem(m_edit_name);
            }
        }

    }

    private void dispatchTakePictureIntent() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);

        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == REQUEST_IMAGE_CAPTURE) {
                Bitmap bitmap = null;

                if (intent != null) {
                    Bundle extras = intent.getExtras();
                    bitmap = (Bitmap) extras.get("data");
                    m_image.setImageBitmap(bitmap);
                }

                if (bitmap != null) {
                    ByteArrayOutputStream stream1 = new ByteArrayOutputStream();
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream1);
                    byte[] imageInByte = stream1.toByteArray();

                    m_db.addChange(mItem.getChromisId(), DatabaseHandler.CHANGETYPE_CHANGEVALUEBLOB,
                            StockProduct.IMAGE, imageInByte, getResources().getString(R.string.captured_image));

                }
            } else {

                ScannerResult scanResult = ScannerIntegrator.parseActivityResult(requestCode, resultCode, intent);
                if (scanResult != null) {
                    String code = scanResult.getContents();

                    if (!TextUtils.isEmpty(code)) {
                        // is this an existing barcode ?
                        DatabaseHandler db = DatabaseHandler.getInstance(getContext());
                        StockProduct product = db.lookupBarcode(code);
                        if (product != null) {
                            // Ask to load the product details activity
                            askDuplicateBarcode(product);
                        } else {
                            // Use the scanned data as the barcode
                            setBarcode(code);
                        }
                    }
                }
            }
        }
    }

    private void setBarcode(String code) {
        DatabaseHandler db = DatabaseHandler.getInstance(getActivity());
        db.addChange(mItem.getChromisId(), DatabaseHandler.CHANGETYPE_CHANGEVALUE, StockProduct.CODE, code, code);
    }

    private void askDuplicateBarcode(StockProduct product) {

        final Long duplicateID = product.getID();
        final String barcode = product.getValueString(StockProduct.CODE);

        AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
        alert.setTitle(getResources().getString(R.string.dlg_barcode_exists_title));
        alert.setMessage(getResources().getString(R.string.dlg_barcode_exists_message));

        alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                // Bring up the existing product
                Intent detailIntent = new Intent(getActivity(), ProductDetailActivity.class);
                detailIntent.putExtra(ProductDetailFragment.ARG_ITEM_ID, duplicateID);
                startActivity(detailIntent);
            }
        });

        alert.setNeutralButton("No", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                // Use the scanned data as the barcode
                setBarcode(barcode);
            }
        });

        alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
            }
        });

        alert.show();

    }

    private void onScanItem(View v) {
        ScannerIntegrator scanner = new ScannerIntegrator(this);
        scanner.initiateScan();
    }

    private void onEditItem(View v) {
        Bundle args = new Bundle();
        boolean bDoDialog = true;

        switch (v.getId()) {
        case R.id.ibAddStock:
            args.putString(StockChangeDialog.ARG_FIELD, StockProduct.QTY_INSTOCK);
            args.putString(StockChangeDialog.ARG_FIELD_LABEL, getResources().getString(R.string.label_instock));
            args.putInt(StockChangeDialog.ARG_CHANGETYPE, DatabaseHandler.CHANGETYPE_ADJUSTVALUE);
            args.putString(StockChangeDialog.ARG_VALUE, "0");
            break;

        case R.id.edit_instock:
            args.putString(StockChangeDialog.ARG_FIELD, StockProduct.QTY_INSTOCK);
            args.putString(StockChangeDialog.ARG_FIELD_LABEL, getResources().getString(R.string.label_instock));
            args.putInt(StockChangeDialog.ARG_CHANGETYPE, DatabaseHandler.CHANGETYPE_CHANGEVALUE);
            args.putString(StockChangeDialog.ARG_VALUE,
                    String.format("%.0f", mItem.getValueDouble(StockProduct.QTY_INSTOCK)));
            break;

        case R.id.edit_name:
            args.putString(StockChangeDialog.ARG_FIELD, StockProduct.NAME);
            args.putString(StockChangeDialog.ARG_FIELD_LABEL, getResources().getString(R.string.label_productname));
            args.putInt(StockChangeDialog.ARG_CHANGETYPE, DatabaseHandler.CHANGETYPE_CHANGEVALUE);
            args.putString(StockChangeDialog.ARG_VALUE, mItem.getValueString(StockProduct.NAME));
            break;

        case R.id.edit_reference:
            args.putString(StockChangeDialog.ARG_FIELD, StockProduct.REFERENCE);
            args.putString(StockChangeDialog.ARG_FIELD_LABEL, getResources().getString(R.string.label_reference));
            args.putInt(StockChangeDialog.ARG_CHANGETYPE, DatabaseHandler.CHANGETYPE_CHANGEVALUE);
            args.putString(StockChangeDialog.ARG_VALUE, mItem.getValueString(StockProduct.REFERENCE));
            break;

        case R.id.edit_barcode:
            args.putString(StockChangeDialog.ARG_FIELD, StockProduct.CODE);
            args.putString(StockChangeDialog.ARG_FIELD_LABEL, getResources().getString(R.string.label_barcode));
            args.putInt(StockChangeDialog.ARG_CHANGETYPE, DatabaseHandler.CHANGETYPE_CHANGEVALUE);
            args.putString(StockChangeDialog.ARG_VALUE, mItem.getValueString(StockProduct.CODE));
            break;

        case R.id.edit_minqty:
            args.putString(StockChangeDialog.ARG_FIELD, StockProduct.QTY_MIN);
            args.putString(StockChangeDialog.ARG_FIELD_LABEL, getResources().getString(R.string.label_minqty));
            args.putInt(StockChangeDialog.ARG_CHANGETYPE, DatabaseHandler.CHANGETYPE_CHANGEVALUE);
            args.putString(StockChangeDialog.ARG_VALUE,
                    String.format("%.0f", mItem.getValueDouble(StockProduct.QTY_MIN)));
            break;

        case R.id.edit_maxqty:
            args.putString(StockChangeDialog.ARG_FIELD, StockProduct.QTY_MAX);
            args.putString(StockChangeDialog.ARG_FIELD_LABEL, getResources().getString(R.string.label_maxqty));
            args.putInt(StockChangeDialog.ARG_CHANGETYPE, DatabaseHandler.CHANGETYPE_CHANGEVALUE);
            args.putString(StockChangeDialog.ARG_VALUE,
                    String.format("%.0f", mItem.getValueDouble(StockProduct.QTY_MAX)));
            break;

        case R.id.edit_pricebuy:
            args.putString(StockChangeDialog.ARG_FIELD, StockProduct.PRICEBUY);
            args.putString(StockChangeDialog.ARG_FIELD_LABEL, getResources().getString(R.string.label_pricebuy));
            args.putInt(StockChangeDialog.ARG_CHANGETYPE, DatabaseHandler.CHANGETYPE_CHANGEVALUE);
            args.putString(StockChangeDialog.ARG_VALUE,
                    String.format("%.2f", mItem.getValueDouble(StockProduct.PRICEBUY)));
            break;

        case R.id.edit_pricesell:
            args.putString(StockChangeDialog.ARG_FIELD, StockProduct.PRICESELL);
            args.putString(StockChangeDialog.ARG_FIELD_LABEL, getResources().getString(R.string.label_pricesell));
            args.putInt(StockChangeDialog.ARG_CHANGETYPE, DatabaseHandler.CHANGETYPE_CHANGEVALUE);
            args.putString(StockChangeDialog.ARG_VALUE,
                    String.format("%.2f", mItem.getValueDouble(StockProduct.PRICESELL)));
            break;

        default:
            bDoDialog = false;
            break;
        }

        if (bDoDialog) {
            // Create an instance of the change dialog fragment and show it
            StockChangeDialog dialog = new StockChangeDialog();

            args.putLong(StockChangeDialog.ARG_PRODUCTID, mItem.getID());

            dialog.setArguments(args);
            dialog.show(getFragmentManager(), "StockChangeDialog");
        }
    }

    private class TaxCatAdapter extends BaseAdapter implements SpinnerAdapter {

        private final List<DatabaseHandler.TaxCat> m_data;

        public TaxCatAdapter(List<DatabaseHandler.TaxCat> data) {
            this.m_data = data;
        }

        @Override
        public int getCount() {
            return m_data.size();
        }

        public int getPosition(String id) {
            int pos = 0;

            if (TextUtils.isEmpty(id)) {
                return -1;
            }

            while (pos < m_data.size()) {
                if (id.compareTo(m_data.get(pos).ChromisId) == 0) {
                    break;
                }
                ++pos;
            }

            if (pos == m_data.size()) {
                return -1;
            }

            return pos;
        }

        @Override
        public Object getItem(int position) {
            return m_data.get(position);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int position, View recycle, ViewGroup parent) {
            TextView text;
            if (recycle != null) {
                // Re-use the recycled view here!
                text = (TextView) recycle;
            } else {
                // No recycled view, inflate the "original" from the platform:
                LayoutInflater inflater = (LayoutInflater) getActivity()
                        .getSystemService(getActivity().LAYOUT_INFLATER_SERVICE);

                text = (TextView) inflater.inflate(R.layout.simple_list_1, parent, false);
            }

            text.setText(m_data.get(position).Name);
            return text;
        }
    }

    private class CategoryAdapter extends BaseAdapter implements SpinnerAdapter {

        private final List<DatabaseHandler.Category> m_data;

        public CategoryAdapter(List<DatabaseHandler.Category> data) {
            this.m_data = data;
        }

        @Override
        public int getCount() {
            return m_data.size();
        }

        @Override
        public Object getItem(int position) {
            return m_data.get(position);
        }

        public int getPosition(String id) {
            int pos = 0;

            if (TextUtils.isEmpty(id)) {
                return -1;
            }

            while (pos < m_data.size()) {
                if (id.compareTo(m_data.get(pos).ChromisId) == 0) {
                    break;
                }
                ++pos;
            }

            if (pos == m_data.size()) {
                return -1;
            }

            return pos;
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int position, View recycle, ViewGroup parent) {
            TextView text;
            if (recycle != null) {
                // Re-use the recycled view here!
                text = (TextView) recycle;
            } else {
                // No recycled view, inflate the "original" from the platform:
                LayoutInflater inflater = (LayoutInflater) getActivity()
                        .getSystemService(getActivity().LAYOUT_INFLATER_SERVICE);

                text = (TextView) inflater.inflate(R.layout.simple_list_1, parent, false);
            }

            text.setText(m_data.get(position).Name);
            return text;
        }
    }
}