I'm using ESPER with JAVA and I'm trying to make a statement that performs a group-by DAY. the property is of DateTime type. I've tryed using
EPStatement cepStatement = cepAdm.createEPL("select sum((NVL(LST.value,TSUR.value)-10.0)/96.0) as add, LST.data.getDayOfMonth() as dia"+
" from LST.win:time(60 min), TSUR.win:time(60 min) "+
"where LST.data.getDayOfMonth() = TSUR.data.getDayOfMonth() and LST.data.getHourOfDay() = TSUR.data.getHourOfDay() "+
"and NVL(LST.value, TSUR.value)>10.0 "+
"Group by LST.data.getDayOfMonth()");
But I'm getting the error "Group-by expressions must refer to property names"...
Try to make the "LST.data.getDayOfMonth()" in the group by use an event property instead for example "LST.data.dayOFMonth". Espers JIRA page is at https://jira.codehaus.org/browse/ESPER in case you want to file an issue or request.
Related
I am trying to create a new KPI in the Digests model to show the number of new customers created per week. (Unfortunately, this functionality is not well documented).
As documented, I have created two fields in the digest model:
x_studio_kpi_new_customers (Boolean)
x_studio_kpi_new_customers_value (Integer)
The value is
for record in self:
start, end, company = record._get_kpi_compute_parameters()
record.x_studio_kpi_new_customers_value = sum(self.env['res.partner'].search([
('x_studio_when', '>=', start),
('x_studio_when', '<', end)
]).mapped('x_studio_counter'))
x_studio_counter is just the value 1 in all records
x_studio_when is the record creation date (have also tried with a datetime field)
I have also tried the code below:
for record in self:
start, end, company = record._get_kpi_compute_parameters()
new_customers = self.env['res.partner'].search_count([('x_studio_when', '>=', start), ('x_studio_when', '<', end)])
record['x_studio_kpi_new_customers_value'] = new_customers
I keep getting 0.
Any help will be appreciated.
In order to build your customized digest, follow these steps:
You may want to add new computed fields with Odoo Studio:
You must create 2 fields on the digest object:
first create a boolean field called kpi_myfield and display it in the KPI's tab;
then create a computed field called kpi_myfield_value that will compute your customized KPI.
Create below "compute_kpis_actions" method and after that digest mail able to view count.
def compute_kpis_actions(self, company, user):
res = super(Digest, self).compute_kpis_actions(company, user)
res['x_studio_kpi_new_customers'] = 'your_module_name.your_action_name&menu_id=%s' % self.env.ref(your_module_name.your_menu_name').id
return res
I am currently trying to setup an approval workflow. I'm fairly junior when it comes to some of this stuff. But so far have it working at respectable level to fit our needs with the assistance of an example.
I was using the template/example from Email Approval using Google Script and a Form.
The issue I am running into, with a lack of functionality is that at the time of Accept or Deny via the Email that is generated for approval I would like it to then record that data back into the Google Form row in the last column that the email was generated from.
I may end up adding 2nd timestamp, reply email etc later.
So then that row would show the initial form filled out and then either blank/accepted/deny as the status.
Thank you for any time or assistance.
The approval workflow that James Ferreira originally wrote was intentionally very basic. Enhancing it to provide correlation between approvals and the original requests is simple in concept, yet complicates the code because of details and limitations.
Things that need to considered:
Form responses include a timestamp, which we can use as a sort of "serial number" for responses, since it has a very high probability of being unique in an application like this.
We can pass this identifier along with the rest of the URL embedded in the approval email, which will give it back as a parameter to the webapp, in turn.
Passing an object like a timestamp between applications can be troublesome. To ensure that the URL embedded in the approval email works, we need to encode the string representation of the timestamp using encodeURIComponent(), then decode it when the webapp consumes it.
Searching for matches is simplified by use of ArrayLib.indexOf() from Romain Vaillard's 2D Array library. This function converts all array data to strings for comparisons, so it fits nicely with our timestamp.
Alternatively, we could put effort into creating some other identifier that would be "guaranteed" to be unique.
The approval-response web app (doGet()) does not understand what "activeSpreadsheet" means, even though it is a script contained within a spreadsheet. This means that we need a way to open the spreadsheet and record the approval result. To keep this example simple, I've assumed that we'll use a constant, and update the code for every deployment. (Ick!).
So here's the Better Expense Approval Workflow script.
// Utilizes 2D Array Library, https://sites.google.com/site/scriptsexamples/custom-methods/2d-arrays-library
// MOHgh9lncF2UxY-NXF58v3eVJ5jnXUK_T
function sendEmail(e) {
// Response columns: Timestamp Requester Email Item Cost
var email = e.namedValues["Requester Email"];
var item = e.namedValues["Item"];
var cost = e.namedValues["Cost"];
var timestamp = e.namedValues["Timestamp"];
var url = ScriptApp.getService().getUrl();
// Enhancement: include timestamp to coordinate response
var options = '?approval=%APPROVE%×tamp=%TIMESTAMP%&reply=%EMAIL%'
.replace("%TIMESTAMP%",encodeURIComponent(e.namedValues["Timestamp"]))
.replace("%EMAIL%",e.namedValues["Requester Email"])
var approve = url+options.replace("%APPROVE%","Approved");
var reject = url+options.replace("%APPROVE%","Rejected");
var html = "<body>"+
"<h2>Please review</h2><br />"+
"Request from: " + email + "<br />"+
"For: "+item +", at a cost of: $" + cost + "<br /><br />"+
"Approve<br />"+
"Reject<br />"+
"</body>";
MailApp.sendEmail(Session.getEffectiveUser().getEmail(),
"Approval Request",
"Requires html",
{htmlBody: html});
}
function doGet(e){
var answer = (e.parameter.approval === 'Approved') ? 'Buy it!' : 'Not this time, Keep saving';
var timestamp = e.parameter.timestamp;
MailApp.sendEmail(e.parameter.reply, "Purchase Request",
"Your manager said: "+ answer);
// Enhancement: store approval with request
var sheet = SpreadsheetApp.openById(###Sheet-Id###).getSheetByName("Form Responses");
var data = sheet.getDataRange().getValues();
var headers = data[0];
var approvalCol = headers.indexOf("Approval") + 1;
if (0 === approvalCol) throw new Error ("Must add Approval column.");
// Record approval or rejection in spreadsheet
var row = ArrayLib.indexOf(data, 0, timestamp);
if (row < 0) throw new Error ("Request not available."); // Throw error if request was not found
sheet.getRange(row+1, approvalCol).setValue(e.parameter.approval);
// Display response to approver
var app = UiApp.createApplication();
app.add(app.createHTML('<h2>An email was sent to '+ e.parameter.reply + ' saying: '+ answer + '</h2>'))
return app
}
So, I tried this, but there an issue with the formatting for date when it's in the data array. In order to get this to work, you have to reformat the time stamp in the doGet using formatDate.
I used the following to get it to match the formatting that appears in the array.
var newDate = Utilities.formatDate(new Date(timestamp) , "PST", "EEE MMM d yyyy HH:mm:ss 'GMT'Z '(PST)'");
Lastly, of course update the indexof parameter that is passed to newDate.
i tried to make this as simple as possible. i`m new to spring batch, i have a small isuue with understanding how to relate spring items together especially when it comes to multi-steps jobs however this is my logic not code(simplified) and i dont know to impliment it in spring batch so i thought this might be the right structure
reader_money
reader_details
tasklet
reader_profit
tasklet_calculation
writer
however please correct me if i`m wrong and provide some code if possible.
thank you very much
LOGIC:
sql = "select * from MONEY where id= user input"; //the user will input the condition
while (records are available) {
int currency= resultset(currency column);
sql= "select * from DETAILS where D_currency = currency";
while (records are available) {
int amount= resultset(amount column);
string money_flag= resultset(money_type column);
sql= "select * from PROFIT where Mtypes = money_type";
while (records are available) {
int revenue= resultset(revenue);
if (money_type== 1) {
int net_profit= revenue * 3.75;
sql = "update PROFIT set Nprofit = net_profit";
}
else (money_type== 2) {
int net_profit = (revenue - 5 ) * 3.7 ;
sql = "update PROFIT set Nprofit = net_profit";
}
}
sql="update DETAILS set detail_falg = 001 ";
}
sql = "update MONEY set currency_flag = 009";
}
to fit this into a 'conventional' spring batch configuration, you would need to flatten the three loops into one if possible.
perhaps a sql statement that would return it in one loop similiar to;
select p.revenue, d.amount from PROFIT p, DETAILS d, MONEY m where p.MTypes = d.money_type and d.D_currency = m.currency and m.id = :?
once you've "flattened" it, you then fall into the more 'conventional' read/process/write of a chunk pattern where the reader retrieves a record from the resultset, the processor performs the money_type logic, and the writer then executes the 'update' statement.
Check for the use of ItemReaderAdapter where you could place all your SQL in some kind of DAO that could return a list of aggregated object containing all the info you need for your calculation.
Or
You could use the CompositeItemReader pattern. You basicaly define multiple ItemReader into one master ItemReader. The read() method will invoke all the inner ItemReader before going to the Processor /writer phase.
I could post you some example.. but i have to leave :-(..
Leave a comment if you need some example
In our Maximo workflow we have a few schemas in which work order reaches a Condition node with a check on a startdate. If current date is less than it's startdate then work order goes to a Wait node with "maximo.workorder.update" condition. So when the scheduled date for WO comes people need to go to WO tracking and save this WO manually. Only then it continues it's way through the workflow. Otherwise WO will sit on that Wait node till the end of time.
What I want to do is to trigger this update event by crontask everyday so when the right date comes WO will wake up by itself.
I inspected source code for a Save button in WO tracking application and found that no matter what there's MboRemoteSet.save() method call. I assumed that you need to get some changes done and then call save() on the right MboSet. Also I know that in DB there's table called EVENTRESPONSE that keeps track of WOs sitting on the Wait nodes in workflow.
My crontask class contains this code:
MXServer mxServer = MXServer.getMXServer();
UserInfo userInfo = mxServer.getUserInfo("maxadmin");
woSet = mxServer.getMboSet("WORKORDER", userInfo);
...
String query = "select sourceid as WORKORDERID from EVENTRESPONSE"
+ " where eventname = 'maximo.workorder.update'"
+ " and sourcetable = 'WORKORDER'";
SqlFormat sqf = new SqlFormat("workorderid IN (" + query + ")");
woSet.setWhere(sqf.format());
MboRemote wo;
Date currentDate = new Date();
for (int i = 0; (wo = woSet.getMbo(i)) != null; i++) {
System.err.println(wo.getString("description"));
wo.setValue("CHANGEDATE", currentDate);
}
woSet.save();
workorder.changedate successfully refreshes but "maximo.workorder.update" event doesn't proc and WO stays on the Wait node.
So, how should I fire maximo.workorder.update?
This response comes a year late, I understand, but it may help others.
It is possible to use an "Escalation" to identify all work orders that have had their time to come and use an action on the escalation to update something on the work order. This will result in Maximo saving the change, thereby triggering the wait node of the workflow, all without any code, just configurations.
I have done something similar in the past and usually I end up flipping a YORN field that I had created for this purpose.
I am working with the neo4j-rest-graphdb an just tried to use Cypher for fetching a simple Node result.
CypherParser parser = new CypherParser();
ExecutionEngine engine = new ExecutionEngine(graphDbService);
Query query = parser.parse( "START referenceNode = node (0) " +
"MATCH referenceNode-[PRODUCTS_REFERENCE]->products-[PRODUCT]->product " +
"RETURN product.productName " +
"ORDER BY product.productId " +
"SKIP 20"
"LIMIT 10");
ExecutionResult result = engine.execute( query );
Iterator<Map<String, Object>> iterator = result.javaIterator();
What is the best practise to iterate through the result? The last line causes my service to hang for ~6 sec. Without the iterator at the end the application is quiet fast. I also tried the webadmin cypher terminal, the results are fetched within 50ms. Am i doing something wrong?
In your case all the cypher operations (graph-matching, filtering etc. would go over the wire which is awfully chatty and slow) you don't want that !
The neo4j-rest-graphdb supports remote execution of cypher out of the box:
Just do, something like shown in this testcase:
RestCypherQueryEngine queryEngine = new RestCypherQueryEngine(restGraphDatabase.getRestAPI());
final String queryString = "start n=node({reference}) return n";
Map params = MapUtil.map("reference",0);
final Node result = (Node) queryEngine.query(queryString, params).to(Node.class).single();
assertEquals(restGraphDatabase.getReferenceNode(), result);
If I understood you correctly, graphDbService is a REST graph database, correct?
If you want to use Cypher on the Server, you should instead use the CypherPlugin. Look here: http://docs.neo4j.org/chunked/snapshot/cypher-plugin.html
I hope this helps,
Andrés