Insert new record(Odoo) - Odoo mobile framework - android

I have a method which accepts an OValue:
getResults(OValues values)
Inside the method are the ff.
ORecordValues value = new ORecordValues();
value.put("order_partner_id", orderline.getPartner(values));
value.put("product_id", orderline.getProduct(values));
value.put("product_uom_qty",values.getInt("product_uom_qty"));
value.put("price_unit", values.getInt("product_uom_qty"));
value.put("discount",values.getInt("product_uom_qty"));
orderline.getServerDataHelper().createOnServer(value);
Is it possible to insert directly to Odoo's server without saving it to android's database?
or any alternative ways to successfully insert data to Odoo server?
In ServerDataHelper java class:
public int createOnServer(ORecordValues data) {
OdooResult result = mOdoo.createRecord(mModel.getModelName(), data);
return result.getInt("result");
}

You need to pass server record id when creating records on the server.
Pass local row id(stored in _id column) to the selectServerId method to get the server id (stored in id column):
Check the following example:
ResPartner resPartner = new ResPartner(getApplicationContext(), null);
ProductProduct productProduct = new ProductProduct(getApplicationContext(), null);
...
ORecordValues value = new ORecordValues();
int partner_id = resPartner.selectServerId(values.getInt("partner_id"));
int product_id = productProduct.selectServerId(values.getInt("product_id"));
value.put("order_partner_id", partner_id);
value.put("product_id", product_id);
value.put("product_uom_qty",values.getInt("product_uom_qty"));
value.put("price_unit", values.getInt("product_uom_qty"));
value.put("discount",values.getInt("product_uom_qty"));
orderline.getServerDataHelper().createOnServer(value);

Related

Prevent data duplication in the SQLite Database

I'm developing an android app that uses SQLite as the local database. The app syncs data obtained from a web api and stores it in the local database. All the model classes have their ID property set as Primary key and Auto incremented so I can manually enter data without having to specify the ID. The issue is when I insert the data from the API into the SQlite, the ID of the object is ignored and Sqlite gives the object a new ID. I want the data stored with the same ID as the object being stored.
The web api returns the object lists that have their ID type long however the SQLite objects have their primary keys as int. Is this the reason why the ID values is not getting stored because their data types don't match? I can't change the datatype in my SQL database where the data comes from as there are hundreds of tables in it. Is there a way around it?
This is the Code to inserts or updates data in my local DB:
}
public async Task<string> insertUpdateVideoData(Video_Struct data)
{
try
{
var db = new SQLiteAsyncConnection(dbPath);
var m = GetVideos();
if (await db.FindAsync<Video_Struct>(f => f.VideoID == data.VideoID) != null)
{
await db.UpdateAsync(data);
}
else
{
if (await db.InsertAsync(data) != 0)
{
await db.UpdateAsync(data);
}
}
return "Single data file inserted or updated";
}
catch (SQLiteException ex)
{
return ex.Message;
}
}
This is the code to get data objects from the API:
public async Task<List<Video_Struct>> GetVideoData()
{
List<Video_Struct> vids = new List<Video_Struct>();
WebClient mClient = new WebClient();
var output = await mClient.DownloadDataTaskAsync(new Uri(GlobalVariables.host + "/api/media/getmedia"));
var json = Encoding.UTF8.GetString(output);
vids = JsonConvert.DeserializeObject<List<Video_Struct>>(json);
return vids;
}
If your local DB is a cache for web data and external DB gives you unique IDs, don't use auto increment in scheme, just re-use external IDs.
Actually, you can have a complex (compound) primary key, it depends on data unique properties.
If you do not work with your data as structured set you can try gson+SharedPreferences. Just don't forget to override equals and hashcode for your data models.
Datatype in not an issue, because sqlite uses INTEGER type.

How to load database data, and store it into array list, and show it into ListVIew

So, I want to build an app to view some data from database. I already have the database, also already made some entities that have exactly same properties name with the column names in database. And also I put the database into database directory by copying from assets folder.
What I want to achieve is, I want to pull some data, and put it into array list, so I can show it in ListView in fragment.
Is there any convenient way to pull some data without querying (like loadAll() function) ?
For now, I'm using cursor to save the pulled data using query, and assign its properties one by one using set function like setName(String name).
After that, I show the list using CursorAdapter.
It would be like this
public class FrameCursor extends CursorWrapper{
/**
* Creates a cursor wrapper.
*
* #param cursor The underlying cursor to wrap.
*/
public FrameCursor(Cursor cursor) {
super(cursor);
}
public ZFrame getFrame(){
if(isBeforeFirst() || isAfterLast()){
return null;
}
ZFrame frame = new ZFrame();
ZFrameDao frameDao = new ZFrameDao();
int frameEdition = getInt(getColumnIndex(COLUMN_FRAME_EDITION));
int frameId = getInt(getColumnIndex(COLUMN_FRAME_ID));
int frameNumber = getInt(getColumnIndex(COLUMN_FRAME_NUMBER));
int frameType = getInt(getColumnIndex(COLUMN_FRAME_TYPE));
int frameBookmark = getInt(getColumnIndex(COLUMN_FRAME_BOOKMARK));
int frameGlyph = getInt(getColumnIndex(COLUMN_FRAME_GLYPH));
int frameLesson = getInt(getColumnIndex(COLUMN_FRAME_LESSON));
String frameAllReading = getString(getColumnIndex(COLUMN_FRAME_ALL_READING));
String frameReadingNumber = getString(getColumnIndex(COLUMN_FRAME_READING_NUMBER));
String frameReference = getString(getColumnIndex(COLUMN_FRAME_REFERENCE));
String frameWritingNumber = getString(getColumnIndex(COLUMN_FRAME_WRITING_NUMBER));
frame.setZEDITION(frameEdition);
frame.setZFRAME_ID(frameId);
frame.setZFRAME_NUMBER(frameNumber);
frame.setZFRAME_TYPE(frameType);
frame.setZBOOKMARK(frameBookmark);
frame.setZGLYPH((long)frameGlyph);
frame.setZLESSON((long)frameLesson);
frame.setZALL_READING_NUMBER(frameAllReading);
frame.setZREADING_NUMBER(frameReadingNumber);
frame.setZREFERENCE(frameReference);
frame.setZWRITING_NUMBER(frameWritingNumber);
return frame;
}
}
It would be consume lot of work for doing this for every table.
So anyone could help me?
Why not using CursorLoader ? Use CursorLoader to handle the cursor query issue, and it works perfectly with CursorAdapter, Here is the google's guide
Maybe this is what you need, a light weight orm api? You can go here for more information.

Adding only unique values into Realm

Is there an elegant way to add a batch of new objects from JSON, taking into consideration that the new bunch might contain values that already in DB and that DB must contain only unique values?
Why not using the same id in the JSON object?, check that a unique id is being sent from the server and prepare a method that checks out for the id if it exists.
//Check if item exists already with id
public boolean checkIfExists(String id){
RealmQuery<Data> query = realm.where(Data.class)
.equalTo("id", id);
return query.count() != 0;
}

Access New ParseObject (Parse.com) Across Activities (Android)

I'm looking for a way to access a newly created local ParseObject which hasn't yet synced to the Parse cloud server. Since there is no objectId value there's no way to query for the objectId through the local datastore and it appears the localId (which looks like it creates a unique identifier locally) is locked down (otherwise this would be a non-issue as I could use my Content Provider to take care of the details). Since the ParseObject class isn't Serializable of Parcelable I can't pass it through an Intent. To note the complexity of my task I have I have 3 levels of ParseObjects (ParseObject > Array[ParseObjects] > Array[ParseObjects]). Essentially I'm looking to see if Parse has full offline capabilities.
TL:DR
Basically I want to be able to access a single ParseObject in a different Activity as soon as it's created. Does this problem have a practical application with Parse and ParseObjects or am I going to have to implement some serious work arounds?
I believe ParseObjects are serializable, so put them into a Bundle and then put that Bundle into an Intent
in the current activity
Intent mIntent = new Intent(currentActivityReference, DestinationActivity.class);
Bundle mBundle = new Bundle();
mBundle.putSerializable("object", mParseObject);
mIntent.putExtras(mBundle);
startActivity(mIntent);
in the destination activity
retrieve the intent with getIntent().getExtras(), which is a Bundle object, so there is a getter for the serializable .getSerializable("object") but you will have to cast it to (ParseObject)
So I was able to keep everything within the confines of the structures I already have in place to take care of this problem (a sync adapter and the Parse API). Basically all I had to do was leverage Parse's existing "setObjectId" function.
NOTE: This only works with an existing Content Provider / SQLiteDatabase
I created a temporary unique ID for the new ParseObject to be stored locally. This unique value is based off of the max index number in the Content Provider I'm storing my objects (for my Sync Adapter).
//query to get the max ID from the Content Provider (used with the sync adapter)
Cursor cursor = context.getContentResolver().query(
WorkoutContract.Entry.CONTENT_URI,
new String[]{"MAX(" + WorkoutContract.Entry._ID + ")"},
null, null, null
);
long idx = 1; //default max index if there are no records
if (cursor.moveToFirst())
idx = cursor.getInt(0) + 1;
final long maxIndex = idx;
cursor.close();
//this is the temporary ID used for storing, a String constant prepended to the max index
String localID = WorkoutContract.LOCAL_WORKOUT_ID + maxIndex;
I then used the pin() method to store this ParseObject locally and then made an insert into the Content Provider to not only keep the ID in the table to iterate the max index in the table.
//need to insert a dummy value into the Content Provider so the max _ID iterates
ContentValues workoutValues = new ContentValues();
//the COLUMN_WORKOUT_ID constant refers to the column which holds the ParseObjects ID
workoutValues.put(WorkoutContract.Entry.COLUMN_WORKOUT_ID, localID);
context.getContentResolver().insert(
WorkoutContract.Entry.CONTENT_URI,
workoutValues);
Then I created another dummy ParseObject with all the same attributes as the one with the local ID (without the local ID). This ParseObject was then saved to the server via the saveEventually() function. (Note: This will create 2 local copies or your ParseObject. To leave the blank copy out of queries simply leave out ParseObjects with null object IDs).
query.whereNotEqualTo("objectId", null);
In the saveEventually() function there needs to be a callback which replaces the old (local) ParseObject as well as the localID value in the Content provider. In the SaveCallback object replace the server returned ParseObject's attributes with the local ones (to account for any changes made during the server query). Below is the full code for the SaveCallback where the tempObject is the one sent to the Parse server:
tempObject.saveEventually(new SaveCallback() {
//changes the local ParseObject's ID to the newly generated one
#Override
public void done(ParseException e) {
if (e == null) {
try {
//replaces the old ParseObject
tempObject.put(Workout.PARSE_FIELD_NAME, newWorkout.get(Workout.PARSE_FIELD_NAME));
tempObject.put(Workout.PARSE_FIELD_OWNER, ParseUser.getCurrentUser());
tempObject.put(Workout.PARSE_FIELD_DESCRIPTION, newWorkout.get(Workout.PARSE_FIELD_DESCRIPTION));
tempObject.pin();
newWorkout.unpinInBackground(new DeleteCallback() {
#Override
public void done(ParseException e) {
Log.i(TAG, "Object unpinned");
}
});
} catch (ParseException e1) {
e1.printStackTrace();
}
//update to content provider with the new ID
ContentValues mUpdateValues = new ContentValues();
String mSelectionClause = WorkoutContract.Entry._ID + "= ?";
String[] mSelectionArgs = {Long.toString(maxIndex)};
mUpdateValues.put(WorkoutContract.Entry.COLUMN_WORKOUT_ID, tempObject.getObjectId());
mUpdateValues.put(WorkoutContract.Entry.COLUMN_UPDATED, tempObject.getUpdatedAt().getTime());
context.getContentResolver().update(
WorkoutContract.Entry.CONTENT_URI,
mUpdateValues,
mSelectionClause,
mSelectionArgs
);
}
}
});
To get the local ParseObject in another Activity just pass the local objectId in an Intent and load it. However, the index of the ParseObject on the Content Provider needs to be passed as well (or it can be retrieved from the unique local ID) so if the ParseObject is ever retrieved again you can check the Content Provider for the updated Object ID and query the correct ParseObject.
This could use a bit of refinement but for now it works.

ORMlite not returning the object I just saved

Here is my code that fails ( it is running within an activity and the DB helper creates the WishList object fine in the database )
DatabaseHelper helper = DatabaseHelper.getInstance( getActivity() );
int savedID = 0;
WishList wl = new WishList();
wl.setName("abc");
try {
savedID = helper.getWishListDao().create(wl);
WishList wl_saved = helper.getWishListDao().queryForId( savedID );
wl_saved.getId();
} catch (SQLException e) {
e.printStackTrace();
}
Here is my entity. The ID field is auto generated.
#DatabaseTable
public class WishList {
#DatabaseField(generatedId = true)
private int id;
#DatabaseField( canBeNull = false , unique = true )
private String name;
#ForeignCollectionField
private ForeignCollection<WishItem> items;
...
What is wrong is the ID that is generated in the Database is not the same one that that ORMlite returns in the call below. It returns 1.
savedID = helper.getWishListDao().create(wl);
The ID in the database is actually 37. Any ideas what I may be doing wrong?
Using version 4.41
ORMLite's Dao.create(...) method does not return the ID of the newly created object but the number of rows in the database that were changed – usually 1. Here are the javadocs for Dao.create(...).
Create a new row in the database from an object. If the object being created uses DatabaseField.generatedId() then the data parameter will be modified and set with the corresponding id from the database. ...
Returns: The number of rows updated in the database. This should be 1.
When ORMLite creates the object, the generated ID is then set to the id field afterwards. To find the ID of your new object you get it from the object itself:
// create returns 1 row changed
helper.getWishListDao().create(wl);
// the id field is set on the w1 object after it was created
savedID = w1.getId();

Categories

Resources