/**
* 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 13/1/15 10:07 AM
*/
package com.odoo.addons.crm.models;
import android.app.ProgressDialog;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import com.odoo.R;
import com.odoo.base.addons.res.ResCompany;
import com.odoo.base.addons.res.ResCountry;
import com.odoo.base.addons.res.ResCurrency;
import com.odoo.base.addons.res.ResPartner;
import com.odoo.base.addons.res.ResUsers;
import com.odoo.core.account.BaseSettings;
import com.odoo.core.orm.ODataRow;
import com.odoo.core.orm.OModel;
import com.odoo.core.orm.OValues;
import com.odoo.core.orm.annotation.Odoo;
import com.odoo.core.orm.fields.OColumn;
import com.odoo.core.orm.fields.types.OBoolean;
import com.odoo.core.orm.fields.types.ODate;
import com.odoo.core.orm.fields.types.ODateTime;
import com.odoo.core.orm.fields.types.OFloat;
import com.odoo.core.orm.fields.types.OInteger;
import com.odoo.core.orm.fields.types.OText;
import com.odoo.core.orm.fields.types.OVarchar;
import com.odoo.core.support.OUser;
import com.odoo.core.utils.JSONUtils;
import com.odoo.core.utils.ODateUtils;
import com.odoo.core.utils.OResource;
import com.odoo.core.utils.reminder.ReminderUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.Date;
import java.util.List;
import odoo.OArguments;
import odoo.ODomain;
public class CRMLead extends OModel {
public static final String TAG = CRMLead.class.getSimpleName();
public static final String AUTHORITY = "com.odoo.core.crm.provider.content.sync.crm_lead";
public static final String KEY_LEAD = "lead";
public static final String KEY_OPPORTUNITY = "opportunity";
private Context mContext;
@Odoo.onChange(method = "partnerIdOnChange")
OColumn partner_id = new OColumn("Customer", ResPartner.class,
OColumn.RelationType.ManyToOne).addDomain("customer", "=", "true");
OColumn name = new OColumn("Name", OVarchar.class).setSize(64)
.setRequired();
OColumn email_from = new OColumn("Email", OVarchar.class).setSize(128);
OColumn street = new OColumn("Street", OText.class);
OColumn street2 = new OColumn("Street2", OText.class);
OColumn city = new OColumn("City", OVarchar.class).setSize(100);
OColumn zip = new OColumn("Zip", OVarchar.class).setSize(20);
OColumn mobile = new OColumn("Mobile", OVarchar.class).setSize(20);
OColumn phone = new OColumn("Phone", OVarchar.class).setSize(20);
OColumn create_date = new OColumn("Creation Date", ODateTime.class);
OColumn description = new OColumn("Internal Notes", OText.class);
@Odoo.api.v7
@Odoo.api.v8
OColumn categ_ids = new OColumn("Tags", CRMCaseCateg.class,
OColumn.RelationType.ManyToMany);
@Odoo.api.v9alpha
OColumn tag_ids = new OColumn("Tags", CRMCaseCateg.class,
OColumn.RelationType.ManyToMany);
OColumn contact_name = new OColumn("Contact Name", OVarchar.class);
OColumn partner_name = new OColumn("Company Name", OVarchar.class);
OColumn opt_out = new OColumn("Opt-Out", OBoolean.class);
OColumn type = new OColumn("Type", OVarchar.class).setDefaultValue("lead");
OColumn priority = new OColumn("Priority", OVarchar.class).setSize(10);
OColumn date_open = new OColumn("Assigned", ODateTime.class);
OColumn date_closed = new OColumn("Closed", ODateTime.class);
OColumn stage_id = new OColumn("Stage", CRMCaseStage.class,
OColumn.RelationType.ManyToOne);
OColumn user_id = new OColumn("Salesperson", ResUsers.class,
OColumn.RelationType.ManyToOne);
OColumn referred = new OColumn("Referred By", OVarchar.class);
OColumn company_id = new OColumn("Company", ResCompany.class,
OColumn.RelationType.ManyToOne);
OColumn country_id = new OColumn("Country", ResCountry.class,
OColumn.RelationType.ManyToOne);
OColumn company_currency = new OColumn("Company Currency",
ResCurrency.class, OColumn.RelationType.ManyToOne);
/**
* Only used for type opportunity
*/
OColumn probability = new OColumn("Success Rate (%)", OFloat.class).setSize(20).setDefaultValue("0.0");
OColumn planned_revenue = new OColumn("Expected Revenue", OFloat.class).setSize(20).setDefaultValue("0.0");
OColumn ref = new OColumn("Reference", OVarchar.class);
OColumn ref2 = new OColumn("Reference 2", OVarchar.class);
OColumn date_deadline = new OColumn("Expected Closing", ODate.class);
OColumn date_action = new OColumn("Next Action", ODate.class);
OColumn title_action = new OColumn("Next Action", OVarchar.class);
OColumn planned_cost = new OColumn("Planned Cost", OFloat.class).setSize(20);
/**
* Extra functional fields
*/
@Odoo.Functional(method = "getDisplayName", store = true, depends = {
"partner_id", "contact_name", "partner_name"})
OColumn display_name = new OColumn("Display Name", OVarchar.class)
.setLocalColumn();
@Odoo.Functional(method = "storeAssigneeName", store = true, depends = {"user_id"})
OColumn assignee_name = new OColumn("Assignee", OVarchar.class).setSize(100)
.setLocalColumn();
@Odoo.Functional(method = "storeStageName", store = true, depends = {"stage_id"})
OColumn stage_name = new OColumn("Stage name", OVarchar.class).setLocalColumn();
OColumn data_type = new OColumn("Data type", OVarchar.class).setSize(34)
.setLocalColumn().setDefaultValue("opportunity");
OColumn is_done = new OColumn("Mark as Done", OInteger.class)
.setLocalColumn().setDefaultValue("0");
OColumn color_index = new OColumn("Color index", OInteger.class).setSize(5)
.setLocalColumn().setDefaultValue(7);
public CRMLead(Context context, OUser user) {
super(context, "crm.lead", user);
mContext = context;
setHasMailChatter(true);
String serie = getOdooVersion().getServer_serie();
if (serie.equals("8.saas~6")) {
categ_ids.setName("tag_ids");
}
}
@Override
public Uri uri() {
return buildURI(AUTHORITY);
}
public ODataRow partnerIdOnChange(ODataRow row) {
ODataRow rec = new ODataRow();
String display_name = "";
String contact_name = "";
ResCountry country = new ResCountry(mContext, null);
try {
rec.put("partner_name", row.getString("name"));
rec.put("partner_name", rec.getString("partner_name"));
if (!row.getString("parent_id").equals("false")) {
if (row.get("parent_id") instanceof JSONArray) {
JSONArray parent_id = new JSONArray(
row.getString("parent_id"));
rec.put("partner_name", parent_id.get(1));
display_name = parent_id.getString(1);
contact_name = parent_id.getString(1);
} else {
ODataRow parent_id = row.getM2ORecord("parent_id").browse();
if (parent_id != null) {
rec.put("partner_name", parent_id.getString("name"));
display_name = parent_id.getString("name");
contact_name = parent_id.getString("name");
}
}
if (!TextUtils.isEmpty(display_name)) {
display_name += " (" + row.getString("name") + ")";
contact_name = row.getString("name");
} else {
display_name += row.getString("name");
}
} else {
display_name = row.getString("name");
}
Integer country_id = 0;
if (!row.getString("country_id").equals("false")) {
if (row.get("country_id") instanceof JSONArray) {
JSONArray country_data = new JSONArray(
row.getString("country_id"));
country_id = country.selectRowId(country_data.getInt(0));
if (country_id == null) {
country_id = 0;
}
} else {
ODataRow country_data = row.getM2ORecord("country_id")
.browse();
if (country_data != null) {
country_id = country_data.getInt(OColumn.ROW_ID);
}
}
if (country_id != 0)
rec.put("country_id", country_id);
}
rec.put("display_name", display_name);
rec.put("contact_name", contact_name);
rec.put("street", row.getString("street"));
rec.put("street2", row.getString("street2"));
rec.put("city", row.getString("city"));
rec.put("zip", row.getString("zip"));
rec.put("email_from", row.getString("email"));
rec.put("phone", row.getString("phone"));
} catch (Exception e) {
e.printStackTrace();
}
return rec;
}
public String getDisplayName(OValues row) {
String name = "";
try {
if (!row.getString("partner_id").equals("false")) {
JSONArray partner_id = new JSONArray(
row.getString("partner_id"));
name = partner_id.getString(1);
} else if (!row.getString("partner_name").equals("false")) {
name = row.getString("partner_name");
}
if (!row.getString("contact_name").equals("false")) {
name += (TextUtils.isEmpty(name)) ? row
.getString("contact_name") : " ("
+ row.getString("contact_name") + ")";
}
if (TextUtils.isEmpty(name)) {
name = "No Partner";
}
} catch (Exception e) {
e.printStackTrace();
}
return name;
}
public String storeAssigneeName(OValues vals) {
try {
if (!vals.getString("user_id").equals("false")) {
JSONArray user_id = new JSONArray(vals.getString("user_id"));
return user_id.getString(1);
}
} catch (Exception e) {
e.printStackTrace();
}
return "Unassigned";
}
public String storeStageName(OValues values) {
try {
JSONArray stage_id = new JSONArray(values.getString("stage_id"));
return stage_id.getString(1);
} catch (Exception e) {
}
return "false";
}
public void convertToOpportunity(final ODataRow lead, final List<Integer> other_lead_ids,
final OnOperationSuccessListener listener) {
new AsyncTask<Void, Void, Void>() {
private ProgressDialog dialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(mContext);
dialog.setTitle(R.string.title_please_wait);
dialog.setMessage(OResource.string(mContext, R.string.title_working));
dialog.setCancelable(false);
dialog.show();
}
@Override
protected Void doInBackground(Void... params) {
try {
odoo.Odoo odoo = getServerDataHelper().getOdoo();
// Creating wizard record
JSONObject values = new JSONObject();
values.put("name", (other_lead_ids.size() > 0) ? "merge" : "convert");
Object partner_id = false;
ODataRow partner = null;
if (!lead.getString("partner_id").equals("false")) {
ResPartner resPartner = new ResPartner(mContext, getUser());
partner = resPartner.browse(lead.getInt("partner_id"));
partner_id = partner.getInt("id");
}
values.put("action", (partner == null) ? "create" : "exist");
values.put("partner_id", partner_id);
JSONObject context = new JSONObject();
context.put("stage_type", "lead");
context.put("active_id", lead.getInt("id"));
other_lead_ids.add(lead.getInt("id"));
context.put("active_ids", JSONUtils.<Integer>toArray(other_lead_ids));
context.put("active_model", "crm.lead");
odoo.updateContext(context);
JSONObject result = odoo.createNew("crm.lead2opportunity.partner", values);
int lead_to_opp_partner_id = result.getInt("result");
// Converting lead to opportunity
OArguments arg = new OArguments();
arg.add(lead_to_opp_partner_id);
arg.add(context);
odoo.call_kw("crm.lead2opportunity.partner", "action_apply", arg.get());
OValues val = new OValues();
val.put("type", "opportunity");
for (int id : other_lead_ids) {
update(selectRowId(id), val);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
dialog.dismiss();
if (listener != null) {
listener.OnSuccess();
}
}
@Override
protected void onCancelled() {
super.onCancelled();
dialog.dismiss();
if (listener != null) {
listener.OnCancelled();
}
}
}.execute();
}
private void _markWonLost(String type, ODataRow record) {
OArguments oArguments = new OArguments();
oArguments.add(new JSONArray().put(record.getInt("id")));
getServerDataHelper().callMethod("case_mark_" + type, oArguments, new JSONObject());
CRMCaseStage stage = new CRMCaseStage(mContext, getUser());
String key = (type.equals("won")) ? "Won" : (record.getString("type").equals("lead")) ? "Dead" : "Lost";
ODataRow row = stage.browse(null, "name = ?", new String[]{key});
if (row != null) {
OValues values = new OValues();
values.put("stage_id", row.getInt(OColumn.ROW_ID));
values.put("stage_name", row.getString("name"));
values.put("probability", row.getFloat("probability"));
update(record.getInt(OColumn.ROW_ID), values);
}
}
/**
* Setting reminder for lead/opportunity
*
* @param row_id
*/
public void setReminder(int row_id) {
ODataRow row = browse(row_id);
String time = " " + BaseSettings.getDayStartTime(mContext);
Date now = new Date();
Bundle extra = row.getPrimaryBundleData();
extra.putString(ReminderUtils.KEY_REMINDER_TYPE, "opportunity");
if (!row.getString("date_deadline").equals("false")) {
row.put("date_deadline", row.getString("date_deadline") + time);
Date date_deadline = ODateUtils.createDateObject(row.getString("date_deadline"),
ODateUtils.DEFAULT_FORMAT, false);
if (now.compareTo(date_deadline) < 0) {
extra.putBoolean("expiry_date", true);
if (ReminderUtils.get(mContext).resetReminder(date_deadline, extra)) {
// Nothing to do. Reminder set for expiry date
}
}
}
if (!row.getString("date_action").equals("false")) {
row.put("date_action", row.getString("date_action") + time);
Date date_action = ODateUtils.createDateObject(row.getString("date_action"),
ODateUtils.DEFAULT_FORMAT, false);
if (now.compareTo(date_action) < 0) {
extra.putBoolean("expiry_date", false);
if (ReminderUtils.get(mContext).resetReminder(date_action, extra)) {
// Nothing to do. Reminder set for next date action
}
}
}
}
public void markWonLost(final String type, final ODataRow record, final OnOperationSuccessListener listener) {
new AsyncTask<Void, Void, Void>() {
private ProgressDialog dialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(mContext);
dialog.setTitle(R.string.title_please_wait);
dialog.setMessage(OResource.string(mContext, R.string.title_working));
dialog.setCancelable(false);
dialog.show();
}
@Override
protected Void doInBackground(Void... params) {
_markWonLost(type, record);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
dialog.dismiss();
if (listener != null) {
listener.OnSuccess();
}
}
@Override
protected void onCancelled() {
super.onCancelled();
dialog.dismiss();
if (listener != null) {
listener.OnCancelled();
}
}
}.execute();
}
public void createQuotation(final ODataRow lead, final String partnerId, final boolean close, final OnOperationSuccessListener listener) {
new AsyncTask<Void, Void, Void>() {
private ProgressDialog dialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(mContext);
dialog.setTitle(R.string.title_please_wait);
dialog.setMessage(OResource.string(mContext, R.string.title_working));
dialog.setCancelable(false);
dialog.show();
}
@Override
protected Void doInBackground(Void... params) {
try {
odoo.Odoo odoo = getServerDataHelper().getOdoo();
// Creating wizard record
JSONObject values = new JSONObject();
ResPartner resPartner = new ResPartner(mContext, getUser());
ODataRow partner = resPartner.browse(new String[]{}, Integer.parseInt(partnerId));
values.put("partner_id", partner.getInt("id"));
values.put("close", close);
JSONObject context = new JSONObject();
context.put("stage_type", lead.getString("type"));
context.put("active_id", lead.getInt("id"));
context.put("active_ids", new JSONArray().put(lead.getInt("id")));
context.put("active_model", "crm.lead");
odoo.updateContext(context);
JSONObject result = odoo.createNew("crm.make.sale", values);
int quotation_wizard_id = result.getInt("result");
// Creating quotation
OArguments arg = new OArguments();
arg.add(quotation_wizard_id);
arg.add(context);
odoo.call_kw("crm.make.sale", "makeOrder", arg.get());
Thread.sleep(500);
// if close = true
if (close)
_markWonLost("won", lead);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
dialog.dismiss();
if (listener != null) {
listener.OnSuccess();
}
}
@Override
protected void onCancelled() {
super.onCancelled();
dialog.dismiss();
if (listener != null) {
listener.OnCancelled();
}
}
}.execute();
}
@Override
public ODomain defaultDomain() {
ODomain domain = new ODomain();
domain.add("|");
domain.add("user_id", "=", getUser().getUser_id());
domain.add("user_id", "=", false);
return domain;
}
public static interface OnOperationSuccessListener {
public void OnSuccess();
public void OnCancelled();
}
}