principles of Autosave - autosave

I have a form that users can use to submit a report. As one of the fields is a text area where they can place quite a long text, I would like to insert a function that autosaves the entry every minute or so, but I'm not sure about the principles behind this.
the solution I can think of is:
Autosave the current entry in the database as a version (eg. Entry_id
= 1, Version = 1, Visibility = FALSE)
After 1 minute, autosave again as Entry_id = 1, Version = 2,
Visibility = FALSE)
Keep repeating the above until either:
User presses "SAVE". In that case, change the visibility of the
last version to TRUE, and remove all other versions (all entries where entry_id == 1 and
Visibility == FALSE)
User chooses not to save ("DISCARD"). In this case I remove all entries where
entry_id == 1 and visibility == FALSE
two considerations:
The above should also work well if the customers is editing an existing entry.
I can't use entry_id as primary key anymore
This seems to work in my mind but I'm wondering if I'm using a very convoluted process, and there is a better one?
Thanks,
P

Once the form is loaded a function will be triggered and it will repeat itself after every 10 seconds (or whatever time you mention). That function will take your form, serialize it and send to a server side script (most probably PHP) and that PHP script will insert that record in database (through AJAX) and return the primary key (id) of this inserted record. Now when function executed for the first time it inserted the record with following parameters:
Entry_id = 1 (or whateverthe primary key at which the record is saved),
Version = 1,
Visibility = FALSE
This function returned a primary key. So now you'll have to put a check at start of your autosave function that checks whether the primary key is returned or not (record inserted) and if this key has been returned then it will again get your form serialize it and sends to another function in your server side script (Update function) along with the primary key returned from first autosave call as a parameter and updates the record against this key in database.
Now user keeps on typing the content and autosave function keeps on firing after every 10 seconds, and data is being inserted (for the first time) and updated constantly. As soon as the user presses save button on the form, again take that primary key and update that record with these values:
Version = 1,
Visibility = TRUE

Related

The difference of a output table generated by aggregation is keyedTable and keyedStreamTable

When the output table generated by aggregation is keyedTable and keyedStreamTable, the results are different
When the aggregation engine uses the tables generated by keyedTable and keyedStreamTable to receive the results, the effect is different. The former can be received, but it cannot be used as a data source for a larger period; the latter does not play an aggregation role, but only intercepts the first record of ticks data per minute.
The code executed by the GUI is as follows:
barColNames=`ActionTime`InstrumentID`Open`High`Low`Close`Volume`Amount`OpenPosition`AvgPrice`TradingDay
barColTypes=[TIMESTAMP,SYMBOL,DOUBLE,DOUBLE,DOUBLE,DOUBLE,INT,DOUBLE,DOUBLE,DOUBLE,DATE]
Choose one of the following two lines of code, and find that the results are inconsistent
/////////// Generate a 1-minute K line (barsMin01) This is an empty table
share keyedTable(`ActionTime`InstrumentID,100:0, barColNames, barColTypes) as barsMin01
//////// This code can be used for aggregation, but it cannot be used as a data source for other periods
share keyedStreamTable(`ActionTime`InstrumentID,100:0, barColNames, barColTypes) as barsMin01
////////Choosing this code does not have an aggregation effect, and it is found that only the first tick of every minute is intercepted.
//////////define the data sources
metrics=<[first(LastPrice), max(LastPrice), min(LastPrice), last(LastPrice), sum(Volume), sum(Amount), sum(OpenPosition), sum(Amount)/sum(Volume)/300, last(TradingDay) ]>
////////////Aggregation engine
//////////// generate 1-min k line, Aggregation engine
nMin01=1*60000
tsAggrKlineMin01 = createTimeSeriesAggregator(name="aggr_kline_min01", windowSize=nMin01, step=nMin01, metrics=metrics, dummyTable=ticks, outputTable=barsMin01, timeColumn=`ActionTime, keyColumn=`InstrumentID,updateTime=500, useWindowStartTime=true)
/////////// subscribe and the 1-min k line will be generated
subscribeTable(tableName="ticks", actionName="act_tsaggr_min01", offset=0, handler=append!{getStreamEngine("aggr_kline_min01")}, batchSize=1000, throttle=1, hash=0, msgAsTable=true)
There are some diffenence between keyedTable and keyedStreamTable:
keyedTable: When adding a new record to the table, the system will automatically check the primary key of the new record. If the primary key of the new record is the same as the primary key of the existing record, the corresponding record in the table will be updated.
keyedStreamTable: When adding a new record to the table, the system will automatically check the primary key of the new record. If the primary key of the new record is the same as the primary key of the existing record, the corresponding record will not be updated.
That is, one of them is for updating and the other is for filtering.
The keyedStreamTable you mentioned "does not play an aggregation role, but intercepts the first record of ticks data per minute", is exactly because you set updateTime=500 in createTimeSeriesAggregator. If updateTime is specified, the calculations may occur multiple times in the current window.
You use keyedStreamTable here to subscribe to this result table, so updateTime cannot be used. If you want to force trigger, you can specify the forceTrigger parameter.

Error : FRM-41337:Cannot populate the list from record group

I have a record group that is using a block item, i.e. where cust_id = :order.cust_id
Sometimes it works, sometimes not.
When I query an existing record, I am able to add a new line and enter the condition code i.e. from the populated record group. But when I enter a new order, the list is empty. I tried to put the code in when-new-record-instance, but I get an error
select profile profile1, profile profile2
from dss.v_unit_conditions
where cust_id = :order.dsp_cust_id
and profile_type = 'UC'
and active = 'Y'
41337 - cannot populate list from record group
If I use that in when-tab-change, then I get the same error.
When you perform query, you acquire :ORDER.DSP_CUST_ID value so Record Group Query fetches something.
On the other hand, when you're entering a new order, I presume that :ORDER.DSP_CUST_ID is empty, query doesn't return anything and raises an error.
It means that :ORDER.DSP_CUST_ID must be known. In order to make the Record Group Query work, consider creating it dynamically, i.e. when :ORDER.DSP_CUST_ID gets its value. As it seems that you're entering it manually, the WHEN-VALIDATE-ITEM might be your choice. Have a look at CREATE_GROUP_FROM_QUERY (and, possibly, POPULATE_GROUP_FROM_QUERY) built-ins. They are described (with examples) in Forms Online Help System.

how to change default settings for the new user (Vtiger CRM)?

When creating new user in Vtiger CRM lot of predefined settings (time zone, currency, etc.) are wrong form specific company setup. But I was unable to find info how to change in settings, nor with script, without getting too deep into file structure.
Is it possible (and how)?
To change the default value during entity creation, you need to change the order of values by setting the first value you want.
In vTiger each picklist has the values store in a table for example vtiger_time_zone for time_zone.
If, for example, you want to set the time zone to "Europe/Amsterdam" you need to find the corresponding value of the key field time_zoneid through query
SELECT * FROM vtiger_time_zone where time_zone = "Europe/Amsterdam"
In my case the corresponding time_zoneid returned by the query is 44.
At this point, it is necessary to change the sort order of the new desidered default value by excuting the query
UPDATE `vtiger_time_zone` SET sortorderid` = '0' WHERE `vtiger_time_zone`.`time_zoneid` = 44;
Finally, it is necessary that to move to the second position the option with time_zone = "Pacific/Midway" (time_zoneid = 1) by executing query
UPDATE `vtiger_time_zone` SET sortorderid` = '1' WHERE `vtiger_time_zone`.`time_zoneid` = 1;
Thew default currency value, instead, is given by the default value stored in $currency_name in config.inc.php and setted during the installation.
Yes you can change the Time Zone, Currency details from CRM GUI only without going into code. Just follow this simple steps.
Login to CRM with any user. After login you will see User Name or Image (If profile picture set) on top right corner. There you will get a link for "My Preference". Click on that link which will allow to change User wise Setting. This setting will be User wise so it will not take effect for other Users.
Cheers!!!!

Oracle APEX | How to change select list value and Submit it dynamically

I have two select lists
1. The first one P4_country_id_B contains countries names
select country_name as d, country_id as r
from countries
2. The second one P4_CITY_ID_B contains cities of a country based on selected value in P4_CITY_ID_B.
select city_name as d, city_id as r
from cities
where country_id = :P4_country_id_B
Everything goes OK without any problem.
BUT
I use Execute PL/SQL Code Dynamic Action to change selected values of those lists like this (for example):
:P4_country_id_B:=country_returned_value;
:P4_CITY_ID_B:=city_returned_value;
Where
country_returned_value : is a one value of countries list values for example (USA)
city_returned_value : is a one value of cities list values for example (NewYourk).
The first selected list value changes but the second list never changes.
Notes:
I used P4_country_id_B,P4_CITY_ID_B as Page Items to Submit for the dynamic action.
I don't whan to submit the page instead of dynamic action
How can I change list values in this case please?.
Thanks in advance.
Cascading select lists are refreshed through ajax.
Change select list 1, select list 2 will be refreshed.
You execute plsql, which in turn will set the value of the items involved. Both are select lists, and one is dependent on the other.
So while both will be set, the change of the first one will cause the second to be refreshed.
In other words, you're doing it too fast. And while there is a solution, the proper way is a bit complex and I wouldn't build it in DA's personally.
You haven't specified how or when you call the code which sets the values for the items. So here I'll just assume a DA with an action of type "Execute JavaScript" (for example)
// perform a call to the ajax callback process to get the country and city id
// there are several ways to provide values to the process if necessary.
// for example through x01, which can be used in the proces like
// apex_application.g_x01
apex.server.process('GET_COUNTRY_DEFAULTS', {x01:""}).done(function(data){
// process returns JSON which contains 2 properties: country_id and city_id
// data.country_id
// data.city_id
// bind a ONE-TIME handler to the after refresh event of the city
// cascading LOVs fire the before and after refresh events like any other
// refreshable element in apex
// a one time handler since the values are different each time this code will
// execute
apex.jQuery("#Px_CITY_ID").one("apexafterrefresh",function(){
// after refresh of the list, attempt to set the value of the list to the
// value retrieved earlier
apex.item(this).setValue(data.city_id);
});
// finally, set the value of the country. Doing this will also trigger the
// refresh of dependent elements
apex.item('Px_CITY_ID').setValue(data.country_id);
// since a handler has been bound, the refresh will occur, the after refresh
// triggers, and the value will be set properly
});
Finally, create a new process on the page under "AJAX Callback", and name it GET_COUNTRY_DEFAULTS
DECLARE
l_country_id NUMBER;
l_city_id NUMBER;
BEGIN
l_country_id := 8;
l_city_id := 789;
htp.p('{"country_id":'||l_country_id||',"city_id":'||l_city_id||'}');
EXCEPTION WHEN OTHERS THEN
-- returning an error while using apex.server.process will prompt the user
-- with the error and halt further processing
htp.p('{"error":"'||sqlerrm||'"}');
END;
That should tie everything together.
I think there is some confusion here. My answer below, assumes, according to your question, the first list name is P4_country_id_B, and the second list name is Cities_LOV. If that is not the case, please clarify.
Your first list called P4_country_id_B, and you assign it to itself through the following statement:
:P4_country_id_B:=country_returned_value;
So basically, nothing has changed, the value of P4_country_id_B is the returned value of your list P4_country_id_B without any need for this assignment. Note, it is not clear to me, what is country_returned_value, because P4_country_id_B holds the returned value.
Secondly, you have a list called Cities_LOV, and you assign the returned value to P4_CITY_ID_B page item, through the following statement:
:P4_CITY_ID_B:=returned_city_value;
Again, I am not sure what is returned_city_value, because Cities_LOV holds the returned value of that list.
I am not sure what you are trying to achieve here. But I assume, you want to allow the user to select the Country first, and then based on that, you want to refresh the Cities list to display the cities in that particular country. If that is the case, then use a dynamic action on P4_country_id_B value change, to refresh the value of Cities_LOV. You only need to pass P4_country_id_B to that dynamic action.
UPDATE
After you corrected the wording of the question, the answer would be like this:
In your child list P4_CITY_ID_B make sure you set the option Cascading LOV parent item(s) to the parent list P4_country_id_B. You do not need the dynamic action. The child list, should refresh upon the change of the parent list. The answer here, goes in details about how to implement cascading list

Live field update in form in Access 2013

So I'm somewhat new to access 2013, anyways, I've created a form in access 2013 based directly off a table, so no queries involved if that matters, and what I'm trying to do is just have a text box that updates the total value of 3 different fields as they're entered.
right now it's just a plain-text box, the control source is "=[Search Cost]+[Update Cost]+[Copy Cost]", and if I close the form entirely and reopen the record it updates the text box with the total for all three, but the customer wants it to update in real time. Any suggestions?
I just tried your scenario in Access 2013 on a simple form and it updated for me in real time as I entered values. However, that was because each of the three fields values had a Default Value of 0 in my test table.
So I suspect this is not updating for you in real time because one or more of those values is null while you are entering data in the form. Access doesn't know what [Some field value]+Null should be (it's an unknown thing) so it won't display a calculated value in real time on your form until you provide a value for each of the three fields.
So how can you get around this?
You can add a Default Value of 0 or some other value to each of the three fields at the table level.
Or you could modify your form expression to use the NZ function which will convert any null values to zero. So use this expression:
=Nz([Search Cost])+Nz([Update Cost])+Nz([Copy Cost])
Either of those options should achieve your end goal I believe. They did in my quick tests.

Resources