corda - 在 VaultCustomQuery 中获取帐户名称
问题描述
我正在尝试从 Corda 获取一些汇总数据,并且正在使用 Accounts 模块。
我的状态:
@BelongsToContract(InvoiceContractTk::class)
class SMInvoiceStateTk constructor(val amount: Amount<Currency>,
val issuedDate : LocalDateTime,
val amountPaid: Amount<IssuedTokenType>,
val paidFrom : Party?,
val seller: AnonymousParty,
val buyer: AnonymousParty,
val typeOfGoods : String,
val quantity : Int,
val paidDate : LocalDateTime?,
val nettAmountReceived: Amount<Currency>,
override val linearId: UniqueIdentifier) : LinearState, QueryableState {
/**
* @constructor
*/
constructor(amount: Amount<Currency>,
issuedDate: LocalDateTime,
amountPaid: Amount<IssuedTokenType>,
paidFrom : Party? = amountPaid.token.issuer,
seller: AnonymousParty,
buyer: AnonymousParty,
typeOfGoods: String,
quantity: Int,
paidDate: LocalDateTime?,
linearId: UniqueIdentifier) :
this(amount,
issuedDate,
amountPaid,
paidFrom,
seller,
buyer,
typeOfGoods,
quantity,
Amount(0, amount.token),
paidDate,
Amount(0, amount.token),
linearId
) { }
/**
* Participants , seller, buyer
*/
override val participants: List<AbstractParty> get() = listOf(seller, buyer).map { it }
/**
* Generates a Mapped Object of State
*
* @param schema
*/
override fun generateMappedObject(schema: MappedSchema): PersistentState {
return when (schema) {
is SMInvoiceTkSchemaV1 -> SMInvoiceTkSchemaV1.PersistantSMTkInvoice(
this.linearId.toString(),
this.amount.toDecimal(),
this.issuedDate,
this.amountPaid.toDecimal(),
this.paidFrom.toString(),
this.seller,
this.buyer,
this.typeOfGoods,
this.quantity,
this.paidDate,
this.nettAmountReceived.toDecimal()
)
else -> throw IllegalArgumentException("Unrecognised schema $schema")
}
}
/**
* Gets the Supported schemas for this object
*/
override fun supportedSchemas(): Iterable<MappedSchema> = listOf(SMInvoiceTkSchemaV1)
架构:
/**
* The Database Schema to hold a record of an [SMInvoiceTkSchema]
*/
object SMInvoiceTkSchema
/**
* Defines the fields for an [SMInvoiceTkSchemaV1]
*/
object SMInvoiceTkSchemaV1 : MappedSchema (
schemaFamily = SMInvoiceTkSchema.javaClass,
version = 1,
mappedTypes = listOf(SMInvoiceTkSchemaV1.PersistantSMTkInvoice::class.java)) {
@Entity
@Table(name ="sm_tkinvoice_states")
/**
* Table SM_INVOICE_STATES
*
* @property invoiceId the id of the Invoice
* @property amount the amount of the invoice
* @property issuedDate the date the invoice was issued
* @property amountPaid the amount has been paid
* @property paidFrom the CBDC account from which theinvoice was paid
* @property seller the seller of the goods on the invoice
* @property buyer the buyer of the goods
* @property typeOfGoods the type of goods purchased
* @property quantity the quantity of goods purchased
* @property paidDate the date the invoice was paid
* @property nettAmountReceived the amount received by the seller after paying the VAT
*/
class PersistantSMTkInvoice(
@Column(name="invoice_Id")
var invoiceId: String,
@Column(name="amount")
var amount: BigDecimal,
@Column(name="issuedDate")
var issuedDate: LocalDateTime,
@Column(name="amountPaid")
var amountPaid: BigDecimal,
@Column(name="paidFrom")
var paidFrom: String,
@Column(name="seller")
var seller: AbstractParty?,
@Column(name="buyer")
var buyer: AbstractParty?,
@Column(name="typeOfGoods")
var typeOfGoods: String,
@Column(name="quantity")
var quantity: Int,
@Column(name="paidDate")
var paidDate: LocalDateTime?,
@Column(name="nettAmountreceived")
var nettAmountReceived: BigDecimal
)
: PersistentState() {
/**
* Default constructor required by hibernate.
*/
constructor(): this(
"",
BigDecimal.ZERO,
LocalDateTime.now(),
BigDecimal.ZERO,
"",
null,
null,
"",
0,
null,
BigDecimal.ZERO
)
}
}
这一切都适用于开具支付发票和运行一些查询。我现在想运行另外 2 个聚合查询,它们相当于:
SELECT buyer,typeOfGoods,Round(SUM(amountPaid),2)
From SM_TKINVOICE_STATES
Group by buyer,typeOfGoods
和
select typeOfGoods,seller,round(SUM(nettAmountReceived),2)
from SM_TKINVOICE_STATES
group by typeOfGoods,seller
strong text 买方将是帐户名称,例如 Alice、Jim、Fred 和卖方 MegaCorp、MiniCorp 等。
我的问题是我似乎只能针对 Persisted 模式聚合查询,而对于买家和卖家来说,这包含 CordaX500 名称,即节点而不是帐户。无论我在 uyer 和 Seller 字段中放置什么,所有存储的都是节点(我相信这是设计使然)
我如何获得这样的结果集:
Alice Adult Clothing 52.60
Alice Books 34.10
Alice Children's Clothing 84.68
Bob Adult Clothing 31.16
Bob Alcohol 41.40
George Energy 101.44
Jim Groceries 52.82
Jim Electrical 46.79
Jim Energy 112.12
Kathy Adult Clothing 40.72
Alice Alcohol 38.45
Alice Children's car seat 40.15
Alice Electrical 41.93
Alice Groceries 56.30
Alice Energy 62.68
Anne Adult Clothing 17.95
Anne Alcohol 10.79
Anne Books 5.68
Anne Children's Clothing 57.98
Anne Children's car seat 31.42
Anne Electrical 60.98
Anne Groceries 64.68
Anne Energy 37.31
Bob Books 27.95
Bob Children's Clothing 41.92
Bob Children's car seat 45.07
Bob Electrical 59.23
...
和
Adult Clothing MegaCompany 234.81
Books MediumCompany 230.45
Children's Clothing MediumCompany 291.78
Alcohol MegaCompany 194.02
Energy ElectricAndGas 573.24
Groceries SmallBusiness 258.37
Electrical SmallBusiness 242.74
Children's car seat MiniCompamy 248.37
Electrical MiniCompamy 208.11
Groceries SoleTrader 317.32
Children's Clothing SoleTrader 186.74
我的流量:
@Suspendable
override fun call(): List<Any> {
val buyerNode = serviceHub.networkMapCache.getNodeByLegalName(CordaX500Name(organisation = "BuyerCWP",locality = "London",country = "GB"))!!.legalIdentities[0]
val sellerNode = serviceHub.networkMapCache.getNodeByLegalName(CordaX500Name(organisation = "SellerCWP",locality = "Glasgow",country = "GB"))!!.legalIdentities[0]
val buyerAccounts = subFlow(AccountsForHost(buyerNode))
val sellerAccountsForHost = subFlow(AccountsForHost(sellerNode))
val buyerIds = buyerAccounts.map {it.state.data.linearId.id}
val criteria = QueryCriteria.VaultQueryCriteria(
status = Vault.StateStatus.UNCONSUMED
)
val sum = builder {SMInvoiceTkSchemaV1.PersistantSMTkInvoice::amountPaid.sum(groupByColumns = listOf(SMInvoiceTkSchemaV1.PersistantSMTkInvoice::buyer ,SMInvoiceTkSchemaV1.PersistantSMTkInvoice::typeOfGoods))}
val sumCriteria = QueryCriteria.VaultCustomQueryCriteria(sum)
val allStates = serviceHub.vaultService.queryBy(
contractStateType = SMInvoiceStateTk::class.java,
criteria = criteria
.and( sumCriteria)
//************** SOMETHING HERE I THINK TO MAP TO ACCOUNT NAMES ************************
)
val otherRes = allStates.otherResults
return otherRes
}
这给了我:
O=BuyerCWP, L=London, C=GB, Adult Clothing, 221.79,
O=BuyerCWP, L=London, C=GB, Alcohol, 213.40,
O=BuyerCWP, L=London, C=GB, Books, 526.20,
O=BuyerCWP, L=London, C=GB, Children's Clothing, 261.40,
O=BuyerCWP, L=London, C=GB, Children's car seat, 547.47,
O=BuyerCWP, L=London, C=GB, Electrical, 541.72,
O=BuyerCWP, L=London, C=GB, Energy, 561.94
...
显然 O=BuyerCWP,L=London,C=GB 应该是 Alice、Jim、Bob 等。
我需要做什么来解决这个问题?
解决方案
你有没有尝试使用这样的东西来获取一个人的帐户列表
val myAccounts = accountService.ourAccounts().map { it.state.data.name }
然后在查询条件中使用它
QueryCriteria.VaultQueryCriteria(externalIds = listOf(myAccount.identifier.id))
尝试从samples-kotlin/Accounts/worldcuppitketbooking看一下工作流测试,我想你会找到你需要的很好的例子。