Answering your question directly: it is possible to create a stream that will "apply some processing to each item and then merge them back in a single value".
Developing your example with some sample code:
case class Item(itemId : String)
case class PurchaseOrder(orderId : String, items : Seq[Item])
val purchaseOrder : PurschaseOrder = ???
If we wanted to process the items with a stream we could, although the exact nature of the reduction was ambiguous in the question so I will not define how the fold is achieved:
type ProcessOutput = ???
def processItem(item : Item) : ProcessOutput = ???
val combinedResult : Future[CombinedResult] =
Source.fromIterator( purchaseOrder.items.toIterator )
.via(Flow[Item] map processItem)
.to(Sink.fold[ProcessOutput](???)(???) )
.run()
Answering your question indirectly,
Consider Futures First
Akka streams are very useful when back pressure is necessary. Back pressure is common when you connect to an external source of data because bp allows your application to determine how fast the data is streamed to you since you are responsible for continuously signaling demand for more data.
In the case you presented in the question there is no need to broadcast demand, and incur the inherent overhead that such communication requires. You already have a collection of items so there's no one to send demand to...
Instead, I think Futures are the best way to go for the case you described:
def futProcess(item : Item)(implicit ec : ExecutionContext) =
Future { processItem(item) }
// same output type as the stream run
val combinedResults : Future[CombinedResult] =
Future.sequence{ purchaseOrder.items map futProcess }
.map{ _ fold[ProcessOutput](???)(???) }
You will get better performance, less complexity from having a full ActorSystem around, and the exact same result as a stream anyway...