How to combine Flux and Mono - kotlin

Assume we have the following function
fun getAnnualData(tenant: String): Flux<DashboardResponse> {
val year = LocalDate.now().year
val annualExpenses = expenseFinder.sumAllByYearAndTenant(year = year, tenant = tenant)
val warehouseExpenses = expenseFinder.sumWarehouseByYearAndTenant(year = year, tenant = tenant)
val annualRevenues = revenueFinder.sumAllByYearAndTenant(year = year, tenant = tenant)
return annualExpenses.zipWith(annualRevenues)
.filter { it.t1._id?.year == year }
.filter { it.t2._id?.year == year }
.map {
DashboardResponse(
period = Period.ANNUAL,
expenses = it.t1,
revenue = it.t2
)
}
}
and I want to add the warehouseExpenses to the returning value. How would I do that?
Where
annualExpenses = Flux
warehouseExpenses = Mono
annualRevenue = Flux

You can simply use a flatMap to combine Mono:
Flux.just(...).zipWith(Flux.just(...))
.filter(...)
.flatMap(tuple -> Mono.just(true).map(m -> new DashboardResponse(tuple.getT1(), tuple.getT2(), m)));

Related

Select one row with same id and match value in another column from another table

I'm currently working on a Spring Boot Webapp where I want to retreive tasks with JPA.
A Task can have multiple requirements and my customer creates requirement_answers which are connected to his wedding. I now want to select all tasks where all the requirement.answer_value are answered with 'true'.
My relevant Database Schema is:
My current query is this:
I now want to check that the task with the same uuid has all requirement_answer with true?
How can I achieve this?
Greetings
EDIT:
My Solution, filtered in Code instead of jpql as I could not get it working
#Query("""
select t, ra
from
Task t,
RequirementAnswer ra,
Requirement r,
Wedding w
where
ra.requirement = r and
w.id = :weddingId and
t member of r.tasks"
""")
fun findByWedding(weddingId: Long): List<Tuple>?
}
Here is the filtering:
fun getTasksByWedding(wedding: Wedding?): List<Task> {
val tasks: MutableMap<Task,String> = mutableMapOf()
wedding?.id?.let { taskRepository.findByWedding(it) } ?.map {
val task = it.get(0) as Task
val requirementAnswer = it.get(1) as RequirementAnswer
tasks[task]?.let { taskAnswer ->
if(taskAnswer != requirementAnswer.answerValue){
tasks.remove(task)
}
}?: let {
if(requirementAnswer.answerValue == "true"){
tasks[task] = requirementAnswer.answerValue
}
}
} ?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Wedding doesn't exist")
return tasks.map { it.key }
}
With SQL you can do use subselects to compare the counts:
select t.*
from task t
join task_requirement tr on t.uuid = tr.task_id
join requirement r on tr.requirement_id = r.id
join requirement_answer ra1 on r.id = ra1.requirement_id
join wedding_requirement_answer wra1 on ra1.id = wra1.requirement_answer_id
where wra1.wedding_id = 1
and ( (select ra2.requirement_id
from requirement_answer ra2
join wedding_requirement_answer wra2 on ra2.id = wra2.requirement_answer_id
where wra2.wedding_id = wra1.wedding_id
and ra2.requirement_id = ra1.requirement_id))
=
(select ra3.requirement_id
from requirement_answer ra3
join wedding_requirement_answer wra3 on ra3.id = wra3.requirement_answer_id
where wra3.wedding_id = wra1.wedding_id
and ra3.requirement_id = ra1.requirement_id
and ra3.answer_value = 'true');

Google Places OpeningHours.getWeekdayText() is NULL for some locations

I'm using google places to retrieve information for a place such as the business name, address, OpenHours and LatLng.
This works 95% of the time, but for some places I receive the error...
"Attempt to invoke virtual method 'java.util.List com.google.android.libraries.places.api.model.OpeningHours.getWeekdayText()' on a null object reference"
Looking on Google maps, I do see these places have open hours information.
//Add a marker when a POI on map is clicked.
map.setOnPoiClickListener { poi ->
map.clear()
val poiMarker = map.addMarker(
MarkerOptions()
.position(poi.latLng)
.title(poi.name)
)
poiMarker?.showInfoWindow()
placeId = poi.placeId
Timber.i("Place ID: $placeId")
//https://developers.google.com/maps/documentation/places/android-sdk/reference/com/google/android/libraries/places/api/net/PlacesClient#fetchPlace(com.google.android.libraries.places.api.net.FetchPlaceRequest)
val placeFields = listOf(Place.Field.ID, Place.Field.NAME, Place.Field.ADDRESS, Place.Field.OPENING_HOURS, Place.Field.LAT_LNG)
val request = FetchPlaceRequest.newInstance(placeId, placeFields)
if (!Places.isInitialized()) {
Places.initialize(requireContext(), apiKey, Locale.US);
}
val placesClient = Places.createClient(requireContext())
placesClient.fetchPlace(request)
.addOnSuccessListener { response: FetchPlaceResponse ->
val place = response.place
setLiveDataPlace(place)
}.addOnFailureListener { exception: Exception ->
if (exception is ApiException) {
Timber.i( "Place not found: ${exception.message}")
}
}
binding.buttonSave.visibility = View.VISIBLE
}
}
fun setLiveDataPlace(place: Place){
placeId = place.id as String
placeName = place.name as String
placeAddress = place.address as String
try {
placeOpenMonday = place.openingHours.weekdayText[0]
placeOpenTuesday = place.openingHours.weekdayText[1]
placeOpenWednesday = place.openingHours.weekdayText[2]
placeOpenThursday = place.openingHours.weekdayText[3]
placeOpenFriday = place.openingHours.weekdayText[4]
placeOpenSaturday = place.openingHours.weekdayText[5]
placeOpenSunday = place.openingHours.weekdayText[6]
} catch(e : Exception) {
Timber.i("Open hours exception: ${e.message}")
}
placeLat = place.latLng.latitude.toString()
placeLng = place.latLng.longitude.toString()
Timber.i("Place: $place")
}

kotlin SQLite database always writing default values, never new ones

here is the class I set up for my database. database handler being the inner class.
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.content.ContentValues
import android.util.Log
import java.sql.Date
class Scores {
var id : Int = 0
var dataBaseName = "ScoreDatabase"
var averageTime = 0.0f
val date = Date(System.currentTimeMillis()).toString()
constructor(averageTime:Float) {
this.averageTime = averageTime
Log.d("Poop", averageTime.toString())
}
constructor()
inner class DataBaseHandler(var context:Context, tableName:String): SQLiteOpenHelper(context, dataBaseName, null,1){
val TABLE_NAME = tableName
val COL_ID = "id"
val COL_AVG = "Average_Time"
val COL_DATE = "Date"
override fun onCreate(db: SQLiteDatabase?) {
val createTable = "CREATE TABLE " + TABLE_NAME +" (" +
COL_ID +" INTEGER PRIMARY KEY AUTOINCREMENT," +
COL_AVG + " VARCHAR(256)," +
COL_DATE +" VARCHAR(256)"
db?.execSQL(createTable)
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
fun insertData(score: Scores){
val db = this.writableDatabase
var cv = ContentValues()
cv.put(COL_AVG,score.averageTime)
cv.put(COL_DATE,score.date)
var result = db.insert(TABLE_NAME,null,cv)
if(result == -1.toLong())
Log.d("POOP", "fail score table in addition")
else
Log.d("POOP", "Success score table in addition" )
}
fun readData(): MutableList<Scores>{
var list: MutableList<Scores> = ArrayList()
val db = this.readableDatabase
val query = "Select * from $TABLE_NAME"
val result = db.rawQuery(query,null)
if (result.moveToFirst()){
do {
var score = Scores()
var id = result.getString(0).toInt()
var AvgTime = result.getString(1).toFloat()
var date = result.getString(2).toString()
list.add(score)
}while (result.moveToNext())
}
result.close()
db.close()
return list
}
}
}
I tried this where the scores class and the handler were two separate classes, but it generated the same results.
here is how I write to the database (from 4 separate activities. in each activity the tablename is different. in this one for example it is 'additionDataBase')
val scores = Scores("%.3f".format(timeKeeper.averageNumber).toFloat())
val db = scores.DataBaseHandler(context, "additionDataBase")
db.insertData(scores)
and here is how I read from the database which is in a different activity that shows the averageTime from each table. here is the code for one of them
val context: Context? = activity
val adb = Scores().DataBaseHandler(context!!,"additionDataBase")
val data = adb.readData()
TextViewAdScore.text = data[0].averageTime.toString() + " " + data[1].date
I think I am missing something, but I can't seem to find what it is.
so far, no matter how many times I do this. the output is always 0.0f
Look at what you do in readData:
var score = Scores()
var id = result.getString(0).toInt()
var AvgTime = result.getString(1).toFloat()
var date = result.getString(2).toString()
list.add(score)
id, AvgTime, and date are retrieved but not used in any way, so your code is equivalent to just writing list.add(Scores()). (Side note: there's no reason for them to be var, and why the case inconsistency between AvgTime and the rest?)

Get price in-app Billing Library

My apk is uploaded in the alpha channel, my products created, the buy button if it works.
I'm trying to show several products to buy in a RecyclerView. The purchases work for me. What I could not do is show the price and title of the products.
In my myadapter.kt file I have the following var var p = ArrayList<String>() and function:
fun queryskudetails() {
billingClient = BillingClient.newBuilder(context).setListener(this).build()
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingServiceDisconnected() {
Log.i("Disconnected", "billing client")
}
override fun onBillingSetupFinished(responseCode: Int) {
billingClient.let { billingClient ->
val skulist = ArrayList<String>()
skulist.add("books")
skulist.add("pens")
skulist.add("keychains")
val params = SkuDetailsParams.newBuilder()
params.setSkusList(skulist).setType(BillingClient.SkuType.INAPP)
billingClient.querySkuDetailsAsync(params.build(), { responseCode, skuDetailsList ->
if (responseCode == BillingClient.BillingResponse.OK && skuDetailsList != null) {
for (skuDetails in skuDetailsList) {
val sku = skuDetails.sku
val price = skuDetails.price
Log.i("skudetails", sku)
Log.i("skuprice", price)
hashMap[sku] = price
println("===== price and sku ======")
println(price)
println(sku)
println("===== /proce and sku ======")
// add price to array p1 (defined as a global variable)
p1.add(price)
}
p = precios
}
})
}
}
})
}
In the section onBindViewHolder which is where I assign the price and title to a textView:
override fun onBindViewHolder(holder: Vholder, position: Int) {
queryskudetails()
print("-----Here array price print [] -----")
println (p)
var text: String = array[position]
Log.i("text", text)
holder.textView.text = text
holder.Price.text = hashMap[text.toLowerCase()].toString() // this does not work for me, retun null
Log.i("price", hashMap["books"].toString())
println(hashMap[array[position]]) // retunr null
holder.btn.setOnClickListener(View.OnClickListener {
Log.i("button", text.toLowerCase())
var skuid = hashMap2[text]
val flowParams = BillingFlowParams.newBuilder()
.setSku(text.toLowerCase())
.setType(BillingClient.SkuType.INAPP)
.build()
val responseCode = billingClient.launchBillingFlow(context as Activity?, flowParams)
})
}
When I show the price in a textview the following code does not work for me:
holder.Price.text = hashMap[text.toLowerCase()].toString() where Price is var Price: TextView = itemView.findViewById(R.id.price)
As a second option I try to use the matrix p1 where I stored all the prices in thequeryskudetails ()function but it returns empty.
How can I do to use the content of the array p1?
The price is stored in the Map: hashMap, to recover it use the sku (identifier in google play console)
hashMap = {sku1=USD 3.99, sku2=USD 1.99, sku3=USD 3.99}
//to recover the values according to the sku (key)
hashMap[sku1] = USD 3.99
hashMap[sku2] = USD 1.99
As I see in your code holder.Price.text = hashMap[text.toLowerCase()].toString() (in the variable Text you must have the identifier (identifier = sku) in order to recover the price of each product ), it is correct, check that in another part is not making conflict or has repeated.

Squeryl geo queries with a postgres backend?

How can I perform geo queries using Squeryl with a postgres backend? The sort of queries I want to run are "return all users within x kilometres", etc.
If geo queries aren't supported directly/through a plugin, how can I run raw SQL queries? I saw one gist and it looked complicated.
Update
Specifically I want to run the following query:
SELECT events.id, events.name FROM events
WHERE earth_box( {current_user_lat}, {current_user_lng},
{radius_in_metres}) #> ll_to_earth(events.lat, events.lng);
This is taken from http://johanndutoit.net/searching-in-a-radius-using-postgres/
This object should solve your problem.
object object RawSql {
def q(query: String, args: Any*) =
new RawTupleQuery(query, args)
class RawTupleQuery(query: String, args: Seq[Any]) {
private def prep = {
val s = Session.currentSession
val st = s.connection.prepareStatement(query)
def unwrap(o: Any) = o match {
case None => null
case Some(ob) => ob.asInstanceOf[AnyRef]
case null => null
case a#AnyRef => a
case a#_ => a
}
for(z <- args.zipWithIndex) {
st.setObject(z._2 + 1, unwrap(z._1))
}
st
}
def toSeq[A1]()(implicit f1 : TypedExpressionFactory[A1,_]) = {
val st = prep
val rs = st.executeQuery
try {
val ab = new ArrayBuffer[A1]
val m1 = f1.thisMapper.asInstanceOf[PrimitiveJdbcMapper[A1]]
while(rs.next)
ab.append(m1.convertFromJdbc(m1.extractNativeJdbcValue(rs, 1)))
ab
}
finally {
rs.close()
st.close()
}
}
def toTupleSeq[A1,A2]()(implicit f1 : TypedExpressionFactory[A1,_], f2 : TypedExpressionFactory[A2,_]) = {
val st = prep
val rs = st.executeQuery
try {
val ab = new ArrayBuffer[(A1,A2)]
val m1 = f1.thisMapper.asInstanceOf[PrimitiveJdbcMapper[A1]]
val m2 = f2.thisMapper.asInstanceOf[PrimitiveJdbcMapper[A2]]
while(rs.next)
ab.append(
(m1.convertFromJdbc(m1.extractNativeJdbcValue(rs, 1)),
m2.convertFromJdbc(m2.extractNativeJdbcValue(rs, 2))))
ab
}
finally {
rs.close()
st.close()
}
}
}
}
I got from this gist:
https://gist.github.com/max-l/9250053