/** * Odoo, Open Source Management Solution * Copyright (C) 2012-today Odoo SA (<http:www.odoo.com>) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version * * This program 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 Affero General Public License for more details * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http:www.gnu.org/licenses/> * * Created on 30/12/14 3:28 PM */ package com.odoo.addons.customers; import android.app.ProgressDialog; import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.widget.SwipeRefreshLayout; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; import android.widget.Toast; import com.odoo.addons.crm.CRMLeads; import com.odoo.addons.crm.CRMOpportunitiesPager; import com.odoo.addons.phonecall.PhoneCallDetail; import com.odoo.base.addons.res.ResPartner; import com.odoo.core.orm.ODataRow; import com.odoo.core.orm.fields.OColumn; import com.odoo.core.support.addons.fragment.BaseFragment; import com.odoo.core.support.addons.fragment.IOnSearchViewChangeListener; import com.odoo.core.support.addons.fragment.ISyncStatusObserverListener; import com.odoo.core.support.drawer.ODrawerItem; import com.odoo.core.support.list.IOnItemClickListener; import com.odoo.core.support.list.OCursorListAdapter; import com.odoo.core.utils.BitmapUtils; import com.odoo.core.utils.IntentUtils; import com.odoo.core.utils.OControls; import com.odoo.core.utils.OCursorUtils; import com.odoo.core.utils.sys.IOnBackPressListener; import com.odoo.R; import com.odoo.widgets.bottomsheet.BottomSheet; import com.odoo.widgets.bottomsheet.BottomSheetListeners; import java.util.ArrayList; import java.util.List; public class Customers extends BaseFragment implements ISyncStatusObserverListener, LoaderManager.LoaderCallbacks<Cursor>, SwipeRefreshLayout.OnRefreshListener, OCursorListAdapter.OnViewBindListener, IOnSearchViewChangeListener, View.OnClickListener, BottomSheetListeners.OnSheetItemClickListener, BottomSheetListeners.OnSheetActionClickListener, IOnBackPressListener, IOnItemClickListener, BottomSheetListeners.OnSheetMenuCreateListener { public static final String KEY = Customers.class.getSimpleName(); public static final String KEY_FILTER_REQUEST = "key_filter_request"; public static final String KEY_CUSTOMER_ID = "key_customer_id"; public static final String KEY_FILTER_TYPE = CRMLeads.KEY_MENU; private View mView; private String mCurFilter = null; private ListView mPartnersList = null; private OCursorListAdapter mAdapter = null; private BottomSheet mSheet = null; private boolean syncRequested = false; public enum Type { Leads, Opportunities } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { setHasOptionsMenu(true); setHasSyncStatusObserver(KEY, this, db()); return inflater.inflate(R.layout.common_listview, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); setHasSwipeRefreshView(view, R.id.swipe_container, this); parent().setOnBackPressListener(this); mView = view; mPartnersList = (ListView) view.findViewById(R.id.listview); mPartnersList.setFastScrollEnabled(true); mPartnersList.setFastScrollAlwaysVisible(true); mAdapter = new OCursorListAdapter(getActivity(), null, R.layout.customer_row_item); mAdapter.setHasSectionIndexers(true, "name"); mAdapter.setOnViewBindListener(this); mPartnersList.setAdapter(mAdapter); mAdapter.handleItemClickListener(mPartnersList, this); setHasFloatingButton(view, R.id.fabButton, mPartnersList, this); getLoaderManager().initLoader(0, null, this); } @Override public void onViewBind(View view, Cursor cursor, ODataRow row) { Bitmap img; if (row.getString("image_small").equals("false")) { img = BitmapUtils.getAlphabetImage(getActivity(), row.getString("name")); } else { img = BitmapUtils.getBitmapImage(getActivity(), row.getString("image_small")); } OControls.setImage(view, R.id.image_small, img); OControls.setText(view, R.id.name, row.getString("name")); OControls.setText(view, R.id.company_name, (row.getString("company_name").equals("false")) ? "" : row.getString("company_name")); OControls.setText(view, R.id.email, (row.getString("email").equals("false") ? " " : row.getString("email"))); } @Override public Loader<Cursor> onCreateLoader(int id, Bundle data) { String where = ""; List<String> args = new ArrayList<>(); if (mCurFilter != null) { where = " name like ? "; args.add(mCurFilter + "%"); } String selection = (args.size() > 0) ? where : null; String[] selectionArgs = (args.size() > 0) ? args.toArray(new String[args.size()]) : null; return new CursorLoader(getActivity(), ((ResPartner) db()).liveSearchURI(), null, selection, selectionArgs, "name"); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { mAdapter.changeCursor(data); if (data.getCount() > 0) { new Handler().postDelayed(new Runnable() { @Override public void run() { OControls.setGone(mView, R.id.loadingProgress); OControls.setVisible(mView, R.id.swipe_container); OControls.setGone(mView, R.id.customer_no_items); setHasSwipeRefreshView(mView, R.id.swipe_container, Customers.this); } }, 500); } else { new Handler().postDelayed(new Runnable() { @Override public void run() { OControls.setGone(mView, R.id.loadingProgress); OControls.setGone(mView, R.id.swipe_container); OControls.setVisible(mView, R.id.customer_no_items); setHasSwipeRefreshView(mView, R.id.customer_no_items, Customers.this); OControls.setImage(mView, R.id.icon, R.drawable.ic_action_customers); OControls.setText(mView, R.id.title, _s(R.string.label_no_customer_found)); OControls.setText(mView, R.id.subTitle, ""); } }, 500); if (db().isEmptyTable() && !syncRequested) { syncRequested = true; onRefresh(); } } } @Override public void onLoaderReset(Loader<Cursor> loader) { mAdapter.changeCursor(null); } @Override public void onItemClick(View view, final int position) { ODataRow row = OCursorUtils.toDatarow((Cursor) mAdapter.getItem(position)); if (row.getInt(OColumn.ROW_ID) == 0) { CustomerQuickCreater customerQuickCreater = new CustomerQuickCreater(new OnLiveSearchRecordCreateListener() { @Override public void recordCreated(ODataRow row) { Cursor cr = getActivity().getContentResolver() .query(db().uri(), null, "id = ?", new String[]{row.getString("id")} , null); cr.moveToFirst(); showSheet(cr); } }); customerQuickCreater.execute(row); } else showSheet((Cursor) mAdapter.getItem(position)); } private void showSheet(Cursor data) { if (mSheet != null) { mSheet.dismiss(); } BottomSheet.Builder builder = new BottomSheet.Builder(getActivity()); builder.listener(this); builder.setIconColor(_c(R.color.body_text_2)); builder.setTextColor(_c(R.color.body_text_2)); builder.setData(data); builder.actionListener(this); builder.setOnSheetMenuCreateListener(this); builder.setActionIcon(R.drawable.ic_action_edit); builder.title(data.getString(data.getColumnIndex("name"))); builder.menu(R.menu.menu_sheet_customer); mSheet = builder.create(); mSheet.show(); } @Override public void onSheetMenuCreate(Menu menu, Object o) { ODataRow row = OCursorUtils.toDatarow((Cursor) o); String address = ((ResPartner) db()).getAddress(row); if (address.equals("false") || TextUtils.isEmpty(address)) { menu.findItem(R.id.menu_customer_location).setVisible(false); } String contact = ResPartner.getContact(getActivity(), row.getInt(OColumn.ROW_ID)); if (contact.equals("false")) { menu.findItem(R.id.menu_customer_call).setVisible(false); } if (row.getString("email").equals("false")) { menu.findItem(R.id.menu_customer_send_message).setVisible(false); } } @Override public Class<ResPartner> database() { return ResPartner.class; } @Override public List<ODrawerItem> drawerMenus(Context context) { List<ODrawerItem> items = new ArrayList<ODrawerItem>(); items.add(new ODrawerItem(KEY).setTitle("Customers") .setIcon(R.drawable.ic_action_customers) .setInstance(new Customers())); return items; } @Override public void onStatusChange(Boolean refreshing) { // Sync Status getLoaderManager().restartLoader(0, null, this); } @Override public void onRefresh() { if (inNetwork()) { parent().sync().requestSync(ResPartner.AUTHORITY); setSwipeRefreshing(true); } else { hideRefreshingProgress(); Toast.makeText(getActivity(), _s(R.string.toast_network_required), Toast.LENGTH_LONG) .show(); } } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); menu.clear(); inflater.inflate(R.menu.menu_partners, menu); setHasSearchView(this, menu, R.id.menu_partner_search); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { } return super.onOptionsItemSelected(item); } @Override public boolean onSearchViewTextChange(String newFilter) { mCurFilter = newFilter; getLoaderManager().restartLoader(0, null, this); return true; } @Override public void onSearchViewClose() { // nothing to do } @Override public void onClick(View v) { switch (v.getId()) { case R.id.fabButton: loadActivity(null); break; } } @Override public void onItemClick(BottomSheet sheet, final MenuItem menu, final Object extras) { sheet.dismiss(); ODataRow row = OCursorUtils.toDatarow((Cursor) extras); switch (menu.getItemId()) { case R.id.menu_customer_opportunity: requestOpportunity(row.getInt(OColumn.ROW_ID), row.getString("name")); break; case R.id.menu_customer_leads: requestLeads(Type.Leads, row.getInt(OColumn.ROW_ID), row.getString("name")); break; case R.id.menu_customer_location: String address = ((ResPartner) db()).getAddress(OCursorUtils.toDatarow((Cursor) extras)); if (!address.equals("false") && !TextUtils.isEmpty(address)) IntentUtils.redirectToMap(getActivity(), address); else Toast.makeText(getActivity(), _s(R.string.label_no_location_found), Toast.LENGTH_LONG).show(); break; case R.id.menu_customer_call: String contact = ResPartner.getContact(getActivity(), row.getInt(OColumn.ROW_ID)); if (!contact.equals("false")) IntentUtils.requestCall(getActivity(), contact); else Toast.makeText(getActivity(), _s(R.string.label_no_contact_found), Toast.LENGTH_LONG).show(); break; case R.id.menu_customer_send_message: if (!row.getString("email").equals("false")) IntentUtils.requestMessage(getActivity(), row.getString("email")); else Toast.makeText(getActivity(), _s(R.string.label_no_email_found), Toast.LENGTH_LONG).show(); break; case R.id.menu_customer_schedule_call: Bundle extra = row.getPrimaryBundleData(); extra.putInt(PhoneCallDetail.KEY_OPPORTUNITY_ID, -1); extra.putBoolean(PhoneCallDetail.KEY_LOG_CALL_REQUEST, true); IntentUtils.startActivity(getActivity(), PhoneCallDetail.class, extra); break; } } private void requestOpportunity(int row_id, String name) { Bundle extra = new Bundle(); extra.putBoolean(KEY_FILTER_REQUEST, true); extra.putInt(KEY_CUSTOMER_ID, row_id); extra.putString("name", name); startFragment(new CRMOpportunitiesPager(), true, extra); } private void requestLeads(Type type, int row_id, String name) { Bundle extra = new Bundle(); extra.putBoolean(KEY_FILTER_REQUEST, true); extra.putInt(KEY_CUSTOMER_ID, row_id); extra.putString(KEY_FILTER_TYPE, type.toString()); extra.putString("name", name); startFragment(new CRMLeads(), true, extra); } @Override public void onItemDoubleClick(View view, int position) { final ODataRow row = OCursorUtils.toDatarow((Cursor) mAdapter.getItem(position)); if (row.getInt(OColumn.ROW_ID) == 0) { CustomerQuickCreater customerQuickCreater = new CustomerQuickCreater(new OnLiveSearchRecordCreateListener() { @Override public void recordCreated(ODataRow row) { loadActivity(row); } }); customerQuickCreater.execute(row); } else loadActivity(row); } @Override public void onSheetActionClick(BottomSheet sheet, Object extras) { if (extras instanceof Cursor) { loadActivity(OCursorUtils.toDatarow((Cursor) extras)); } } private void loadActivity(ODataRow row) { Bundle data = null; if (row != null) { data = row.getPrimaryBundleData(); } IntentUtils.startActivity(getActivity(), CustomerDetails.class, data); } @Override public boolean onBackPressed() { if (mSheet != null && mSheet.isShowing()) { mSheet.dismiss(); return false; } return true; } private class CustomerQuickCreater extends AsyncTask<ODataRow, Void, ODataRow> { private ProgressDialog progressDialog; private OnLiveSearchRecordCreateListener mOnLiveSearchRecordCreateListener; public CustomerQuickCreater(OnLiveSearchRecordCreateListener listener) { mOnLiveSearchRecordCreateListener = listener; } @Override protected void onPreExecute() { super.onPreExecute(); progressDialog = new ProgressDialog(getActivity()); progressDialog.setTitle(R.string.title_working); progressDialog.setMessage(_s(R.string.title_please_wait)); progressDialog.setCancelable(false); progressDialog.show(); } @Override protected ODataRow doInBackground(ODataRow... params) { try { Thread.sleep(500); return db().quickCreateRecord(params[0]); } catch (Exception e) { } return null; } @Override protected void onPostExecute(ODataRow row) { super.onPostExecute(row); progressDialog.dismiss(); getLoaderManager().restartLoader(0, null, Customers.this); if (mOnLiveSearchRecordCreateListener != null && row != null) { mOnLiveSearchRecordCreateListener.recordCreated(row); } } } public interface OnLiveSearchRecordCreateListener { public void recordCreated(ODataRow row); } }