Commit 05817f17 authored by Alzhan Turlybekov's avatar Alzhan Turlybekov
Browse files

update 10 tutorial. Update and add java for 12, 13, 14, 15 tutorials

parent 091acdcf
......@@ -8,6 +8,8 @@ groups:
- BASIC-TRAINING-EXCHANGE-APP
keylist:
- id
mappers:
- basics-exchange-currency-orders:1.0
steps:
[
"BasicsExchangeRatesInsertToOrdersTable:1.0"
......
......@@ -3,8 +3,6 @@
%require-types
%enable-all-warnings
%requires SqlUtil
class BasicsExchangeRatesInsertToOrdersTable inherits QorusNormalStep {
primary() {
InboundTableMapper mapper = getMapper("basics-exchange-currency-orders");
......
# This is a generated file, don't edit!
type: step
name: BasicsExchangeRatesInsertToOrdersTable
desc: "Inserts orders from static data into orders table"
author:
- Qore Technologies, s.r.o.
base-class-name: QorusNormalStep
class-name: BasicsExchangeRatesInsertToOrdersTable
lang: qore
version: "1.0"
steptype: NORMAL
code: BasicsExchangeRatesInsertToOrdersTable-1.0.qstep
......@@ -19,7 +19,7 @@ class BasicsSendEmailToUserJava extends QorusNormalStep {
logInfo("Sending email to %s", userEmail);
Message message = new Message("test.qorus@gmail.com", "Order details");
String text = "You have received " + (double)order.get("amount") + " " + (String)order.get("currency_to_buy");
String text = "You have received " + order.get("amount").toString() + " " + (String)order.get("currency_to_buy");
message.setBody(text);
message.addTO(userEmail);
smtp.sendMessage(message);
......
......@@ -23,14 +23,15 @@ class BasicsSendMoneyToBankJava extends QorusNormalStep {
throw new Exception("BUSINESS-ERROR: exchange rate for " + currencyToSell + " is missing");
}
double rate = (double)exchangeRates.get(currencyToBuy);
Number rate = (Number)exchangeRates.get(currencyToBuy);
logInfo("rate: %y", rate);
double amount = (double)order.get("amount");
double sellRate = (double)exchangeRates.get(currencyToSell);
double amountToSend = (amount / rate) * sellRate;
Number amount = (Number)order.get("amount");
Number sellRate = (Number)exchangeRates.get(currencyToSell);
double amountToSend = (amount.doubleValue() / rate.doubleValue()) * sellRate.doubleValue();
amountToSend += amountToSend * (double)getConfigItemValue("bank-commission");
Number commission = (Number)getConfigItemValue("bank-commission");
amountToSend += amountToSend * commission.doubleValue();
logInfo("Money sent to bank: %f %s", amountToSend, currencyToSell);
}
}
......
......@@ -4,12 +4,13 @@ import com.qoretechnologies.qorus.workflow.*;
import java.util.Map;
class BasicsSendMoneyToUserJava extends QorusNormalStep {
@SuppressWarnings("unchecked")
public void primary() throws Throwable {
Map<String, Object> orders = (Map<String, Object>)getStaticData("orders");
for (String key : orders.keySet()) {
Map<String, Object> order = (Map<String, Object>)orders.get(key);
logInfo("Money sent to user: %d %s", (double)order.get("amount"), (String)order.get("currency_to_buy"));
logInfo("Money sent to user: %d %s", order.get("amount").toString(), order.get("currency_to_buy").toString());
}
}
}
# This is a generated file, don't edit!
type: mapper
name: basics-process-orders-job-mapper
desc: "Mapper for workflow order creation from the job"
author:
- Qore Technologies, s.r.o.
fields:
staticdata.exchange_rates:
name: exchange_rates
staticdata.orders:
name: orders
options:
mapper-input:
can_manage_fields: true
custom-fields:
exchange_rates:
canBeNull: false
desc: exchange rates from the API
firstCustomInHierarchy: true
isChild: false
isCustom: true
level: 0
name: exchange_rates
parentPath: false
path: exchange_rates
type:
base_type: hash<auto>
can_manage_fields: true
fields: {}
mandatory: true
name: hash<auto>
options:
qore.no_null: true
supported_options:
qore.no_null:
desc: >-
if True then NULL is not supported on input if
NOTHING is also not accepted
type: bool
typename: hash
types_accepted:
- hash<auto>
types_returned:
- hash<auto>
orders:
canBeNull: false
desc: orders to be processed
firstCustomInHierarchy: true
isChild: false
isCustom: true
level: 0
name: orders
parentPath: false
path: orders
type:
base_type: hash<auto>
can_manage_fields: true
fields: {}
mandatory: true
name: hash<auto>
options:
qore.no_null: true
supported_options:
qore.no_null:
desc: >-
if True then NULL is not supported on input if
NOTHING is also not accepted
type: bool
typename: hash
types_accepted:
- hash<auto>
types_returned:
- hash<auto>
name: qore
path: /hash
type: type
mapper-output:
can_manage_fields: false
custom-fields:
exchange_rates:
canBeNull: false
desc: exchange rates from the API
firstCustomInHierarchy: true
isChild: true
isCustom: true
level: 1
name: exchange_rates
parent: staticdata
parentPath: staticdata
path: staticdata.exchange_rates
type:
base_type: hash<auto>
can_manage_fields: true
fields: {}
mandatory: true
name: hash<auto>
options:
qore.no_null: true
supported_options:
qore.no_null:
desc: >-
if True then NULL is not supported on input if
NOTHING is also not accepted
type: bool
typename: hash
types_accepted:
- hash<auto>
types_returned:
- hash<auto>
orders:
canBeNull: false
desc: orders to be processed
firstCustomInHierarchy: true
isChild: true
isCustom: true
level: 1
name: orders
parent: staticdata
parentPath: staticdata
path: staticdata.orders
type:
base_type: hash<auto>
can_manage_fields: true
fields: {}
mandatory: true
name: hash<auto>
options:
qore.no_null: true
supported_options:
qore.no_null:
desc: >-
if True then NULL is not supported on input if
NOTHING is also not accepted
type: bool
typename: hash
types_accepted:
- hash<auto>
types_returned:
- hash<auto>
name: qoretechnologies
path: /building-blocks/create-order/request
type: type
mappertype: Mapper
version: "1.0"
# name: basics-process-orders-job
# version: 1.0
# desc: Creates BASICS-PROCESS-ORDERS-WORKFLOW orders
# author: Alzhan Turlybekov (Qore Technologies)
# schedule: */1 * * * *
# define-group: BASIC-TRAINING-EXCHANGE-APP: Basic training exchange application objects
# groups: BASIC-TRAINING-EXCHANGE-APP
# class-name: BasicsProcessOrdersJob
# class-based: true
# TAG: basics-training: true
%new-style
%strict-args
%require-types
%new-style
%enable-all-warnings
%requires SqlUtil
%requires RestClient
class BasicsProcessOrdersJob inherits QorusJob {
hash<auto> getRates(string symbols) {
class BasicsProcessOrdersClass inherits UserApi {
*hash getParams() {
*list orders = getOrders();
if (!orders) {
return {};
}
prepareOrdersList(\orders);
hash orders_hash;
foreach hash<auto> order in (orders) {
orders_hash{order.id} = order;
}
logDebug("Orders: %N", orders_hash);
hash rates = getRates(getCurrencyList(orders));
return {
"exchange_rates": rates,
"orders": orders_hash
};
}
private hash getRates(string symbols) {
RestClient exchange_rates_api = getUserConnection("exchange-rates-api");
hash<auto> result = exchange_rates_api.get("/latest?symbols=" + symbols);
......@@ -26,16 +36,19 @@ class BasicsProcessOrdersJob inherits QorusJob {
return result.body.rates;
}
string getCurrencyList(reference<list> orders) {
hash<string, bool> currencies;
string email = propGet(getInfo().name, "email");
private prepareOrdersList(reference<list> orders) {
string email = getConfigItemValue("user_email");
foreach hash<auto> order in (\orders) {
order += {"user_email": email};
order.currency_to_buy = order.currency_to_buy.upr();
order.currency_to_sell = order.currency_to_sell.upr();
}
}
private string getCurrencyList(list orders) {
hash<string, bool> currencies;
foreach hash<auto> order in (orders) {
if (order.currency_to_buy != "EUR") {
currencies{order.currency_to_buy} = True;
}
......@@ -46,49 +59,12 @@ class BasicsProcessOrdersJob inherits QorusJob {
return currencies.keys().join(",");
}
hash prepareOrderData(reference<list> orders) {
hash<auto> rates = getRates(getCurrencyList(\orders));
list order_ids = map $1.id, orders.iterator();
hash order_data = {
"staticdata": {
"orders": orders,
"exchange_rates": rates,
},
"orderkeys": ("ids": order_ids),
"workflow_unique_key": ("ids": order_ids), # ensures order is created once for unique values
};
log(LL_INFO, "Order data: %N", order_data);
return order_data;
}
createWorkflowOrder(reference<list> orders) {
log(LL_INFO, "Orders to be processed: %N", orders);
try {
softstring workflow_instance_id = createOrder("BASICS-PROCESS-ORDERS-WORKFLOW",
NOTHING,
prepareOrderData(\orders));
log(LL_INFO, "Created wf instance id: %d", workflow_instance_id);
} catch (hash ex) {
if (ex.err == "DUPLICATE-ORDER-KEY") {
log(LL_INFO, "Order with the same order key was already created, do not create order");
return;
}
rethrow;
}
}
run() {
log(LL_INFO, "Job is run");
DatasourcePool omquser_ds = getDatasourcePool("omquser");
on_success omquser_ds.commit();
on_error omquser_ds.rollback();
private *list getOrders() {
DatasourcePool ds = getDatasourcePool("omquser");
on_success ds.commit();
on_error ds.rollback();
SqlUtil::AbstractTable orders_table = getSqlTable(omquser_ds, "exchange_orders");
SqlUtil::AbstractTable orders_table = getSqlTable(ds, "exchange_orders");
*list orders = orders_table.selectRows(
{
"where": {"status": "new"},
......@@ -98,10 +74,9 @@ class BasicsProcessOrdersJob inherits QorusJob {
if (!orders) {
log(LL_INFO, "No orders to be processed");
return;
return NOTHING;
}
createWorkflowOrder(\orders);
return orders;
}
}
# END
\ No newline at end of file
# This is a generated file, don't edit!
type: class
name: BasicsProcessOrdersClass
desc: "## Helper class to get new orders from the exchange_orders table\n\nIt has one connector to be used in order to retrive new exchange orders"
author:
- Qore Technologies, s.r.o.
class-connectors:
- name: BasicsProcessOrdersClass1
method: getParams
output-provider:
can_manage_fields: true
name: qore
path: /hash
type: type
type: output
class-name: BasicsProcessOrdersClass
lang: qore
version: "1.0"
code: BasicsProcessOrdersClass-1.0.qclass
import com.qoretechnologies.qorus.*;
import com.qoretechnologies.qorus.job.*;
import org.qore.jni.QoreJavaApi;
import org.qore.jni.QoreObject;
import java.util.Map;
import java.util.Optional;
import java.util.HashMap;
import java.lang.reflect.Method;
import org.qore.lang.mapper.Mapper;
class BasicsProcessOrdersJobJava extends QorusJob {
// ==== GENERATED SECTION! DON'T EDIT! ==== //
ClassConnections_BasicsProcessOrdersJobJava classConnections;
// ======== GENERATED SECTION END ========= //
BasicsProcessOrdersJobJava() throws Throwable {
// ==== GENERATED SECTION! DON'T EDIT! ==== //
classConnections = new ClassConnections_BasicsProcessOrdersJobJava();
// ======== GENERATED SECTION END ========= //
}
// ==== GENERATED SECTION! DON'T EDIT! ==== //
public void run() throws Throwable {
Map<String, Object> data = getData();
classConnections.Connection_1(Optional.of(data));
}
// ======== GENERATED SECTION END ========= //
}
// ==== GENERATED SECTION! DON'T EDIT! ==== //
class ClassConnections_BasicsProcessOrdersJobJava {
// map of prefixed class names to class instances
private final HashMap<String, Object> classMap;
ClassConnections_BasicsProcessOrdersJobJava() throws Throwable {
UserApi.startCapturingObjects();
classMap = new HashMap<String, Object>() {
{
put("BBM_CreateOrder", QoreJavaApi.newObjectSave("BBM_CreateOrder"));
}
};
UserApi.stopCapturingObjects();
}
Object callClassWithPrefixMethod(final String prefixedClass, final String methodName,
Optional<Map<String, Object>> params) throws Throwable {
UserApi.logInfo("ClassConnections_BasicsProcessOrdersJobJava: callClassWithPrefixMethod: method: %s, class: %y", methodName, prefixedClass);
final Object object = classMap.get(prefixedClass);
if (object instanceof QoreObject) {
QoreObject qoreObject = (QoreObject)object;
if (params.isPresent()) {
return qoreObject.callMethod(methodName, params.get());
}
return qoreObject.callMethod(methodName);
} else if (params.isPresent()) {
final Method method = object.getClass().getMethod(methodName, Object.class);
return method.invoke(object, params.get());
} else {
final Method method = object.getClass().getMethod(methodName);
return method.invoke(object);
}
}
@SuppressWarnings("unchecked")
public Object Connection_1(Optional<Map<String, Object>> params) throws Throwable {
Mapper mapper;
UserApi.logInfo("Connection_1 called with data: %y", params);
mapper = UserApi.getMapper("exchange-currency-api-mapper");
params = mapper.mapData(params);
UserApi.logInfo("calling createOrder: %y", params);
return callClassWithPrefixMethod("BBM_CreateOrder", "createWorkflowOrderConnector", params);
}
}
// ======== GENERATED SECTION END ========= //
%new-style
%strict-args
%require-types
%enable-all-warnings
class BasicsProcessOrdersJob inherits QorusJob {
private {
####### GENERATED SECTION! DON'T EDIT! ########
ClassConnections_BasicsProcessOrdersJob class_connections;
############ GENERATED SECTION END ############
}
constructor() {
####### GENERATED SECTION! DON'T EDIT! ########
class_connections = new ClassConnections_BasicsProcessOrdersJob();
############ GENERATED SECTION END ############
}
####### GENERATED SECTION! DON'T EDIT! ########
run() {
class_connections.Connection_1();
}
############ GENERATED SECTION END ############
}
####### GENERATED SECTION! DON'T EDIT! ########
class ClassConnections_BasicsProcessOrdersJob {
private {
# map of prefixed class names to class instances
hash<auto> class_map;
}
constructor() {
class_map = {
"BasicsProcessOrdersClass": new BasicsProcessOrdersClass(),
"BBM_CreateOrder": new BBM_CreateOrder(),
};
}
auto callClassWithPrefixMethod(string prefixed_class, string method) {
UserApi::logDebug("ClassConnections_BasicsProcessOrdersJob: callClassWithPrefixMethod: method: %s, class: %y", method, prefixed_class);
return call_object_method_args(class_map{prefixed_class}, method, argv);
}
auto Connection_1(*hash<auto> params) {
auto mapper;
UserApi::logDebug("Connection_1 called with data: %y", params);
UserApi::logDebug("calling BasicsProcessOrdersClass1: %y", params);
params = callClassWithPrefixMethod("BasicsProcessOrdersClass", "getParams", params);
if (!params) {
UserApi::logDebug("no data - skip wf order creation");
return;
}
mapper = UserApi::getMapper("basics-process-orders-job-mapper");
params = mapper.mapData(params);
UserApi::logDebug("calling createOrder: %y", params);
return callClassWithPrefixMethod("BBM_CreateOrder", "createWorkflowOrderConnector", params);
}
}
############ GENERATED SECTION END ############
# This is a generated file, don't edit!
type: job
name: basics-process-orders-job-java
desc: "Creates BASICS-PROCESS-ORDERS-WORKFLOW-java orders"
name: basics-process-orders-job
desc: "Creates BASICS-PROCESS-ORDERS-WORKFLOW orders"
author:
- Qore Technologies, s.r.o.
base-class-name: QorusJob
class-name: BasicsProcessOrdersJobJava
class-name: BasicsProcessOrdersJob
classes:
- BBM_CreateOrder
- BasicsProcessOrdersClass
groups:
- BASIC-TRAINING-EXCHANGE-APP
lang: java
lang: qore
mappers:
- exchange-currency-api-mapper:1.0
- basics-process-orders-job-mapper:1.0
schedule:
minutes: "*/1"
hours: "*"
......@@ -20,13 +21,15 @@ schedule:
months: "*"
dow: "*"
version: "1.0"
code: BasicsProcessOrdersJobJava.java
code: basics-process-orders-job-1.0.qjob
class-connections:
Connection_1:
- class: BasicsProcessOrdersClass
connector: BasicsProcessOrdersClass1
trigger: run