首页 > 解决方案 > 在 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 等。

我需要做什么来解决这个问题?

标签: corda

解决方案


你有没有尝试使用这样的东西来获取一个人的帐户列表

val myAccounts = accountService.ourAccounts().map { it.state.data.name }

然后在查询条件中使用它

QueryCriteria.VaultQueryCriteria(externalIds = listOf(myAccount.identifier.id))

尝试从samples-kotlin/Accounts/worldcuppitketbooking看一下工作流测试,我想你会找到你需要的很好的例子。


推荐阅读