I would like to create a query which returns all the Requests (asset) in which the Container's (asset) owner's id is equal to the parameter.
Model file (owner of a container is a Company participant, identified by id):
namespace org.acme.shipping.assets
import org.acme.shipping.participants.*
asset Container identified by number {
o String number
o ContainerType type
o String content
o ContainerStatus status default = "FREE"
--> Company owner
}
enum ContainerType {
o DRY
o REEFER
}
enum ContainerStatus {
o LOCKED
o FREE
}
asset Request identified by id {
o String id
--> Container container
}
Query file
query getRequestsByCompany {
description: "Get requests by company"
statement:
SELECT org.acme.shipping.assets.Request
WHERE (container.owner.id == _$company_id)
}
However, the current query does not seem to work. Is this achievable with a query?
I did a lot of research also to do it using query file, but couldnt find a way, so I think that its not possible at moment.
The alternative way is to use loopback filters:
https://github.com/hyperledger/composer-knowledge-wiki/blob/latest/knowledge.md#information_source--filters-loopback
https://loopback.io/doc/en/lb2/Where-filter.html
Something like:
{"where":{"shipmentId":1000}, "include":"resolve"}
you can go one level in like search by number . I am working on it if get the exact solution .
query getRequestsByCompany {
description: "Get requests by company"
statement:
SELECT org.acme.shipping.assets.Request
WHERE (container == _$container)
}
Related
I am getting bellow error while playing around Hyperledger Composer.
{
"$class": "org.property.registration.purchaseProperty",
"propertyListing":
"resource:org.property.registration.PropertyListing#PL001"
}
Error: attempt to get property owner on an InvalidRelationship is not allowed. InvalidRelationship created due to Object with ID '1003' in collection with ID 'Asset:org.property.registration.Property' does not exist; [cause=Participant 'org.property.registration.User#0001' does not have 'READ' access to resource 'org.property.registration.Property#1003']
I am trying to access Asset property which is a part of another asset propertyListing.
asset Property identified by PID {
o String PID
o Integer marketPrice
o DateTime regDate
o String propertyType
o String location
o String status default= "Registered"
--> User owner
}
asset PropertyListing identified by PLID {
o String PLID
--> Property property
}
I am trying to access PropertyListing asset and change status of property asset inside it.
(I want to purchase the property from the propertyListing posted by some other user)
const registry = await getAssetRegistry(tx.propertyListing.property.getFullyQualifiedType());
await registry.update(tx.propertyListing.property);
// Remove the property from propertyListing()
const registry2 = await getAssetRegistry(tx.propertyListing.getFullyQualifiedType());
await registry2.remove(tx.propertyListing);
I hope and as per the error message it seems like some permission issue which is blocking me to purchase the property post by other user.
// User can see all properties listed for sale
rule UserAccessAllSaleProperties {
description: "Allow Users to access all properties listed for sale"
participant: "org.property.registration.User"
operation: ALL
resource: "org.property.registration.PropertyListing"
action: ALLOW
}
Here i want to access the property which is part of PropertyListing.
I am trying to find what short of ACL i can use. Still trying.
Guys your suggestions are welcome!!!
Try,
rule UserAccessAllSaleProperties {
description: "Allow Users to access all properties listed for sale"
participant: "org.property.registration.**"
operation: READ
resource: "org.property.registration.PropertyListing"
action: ALLOW
}
This will allow all participants to only "READ" the PropertyListing Asset which will be better suited to your application. It will be beneficial if you introduce any future participants. (Assuming User is defined as a participant and not an asset).
I would also recommend separating your participant and Asset files since you have a big application.
like
org.property.registration.Property (-> Will only contain Assets)
org.property.registration.Participants (-> Will only contain Participants)
And import them into each other.
so your rule will be like
rule UserAccessAllSaleProperties {
description: "Allow Users to access all properties listed for sale"
participant: "org.property.registration.Participants.**"
operation: READ
resource: "org.property.registration.PropertyListing"
action: ALLOW
}
When releasing documents the scan operator should get logged to a file. I know this is a kofax system variable but how do I get it from the ReleaseData object?
Maybe this value is hold by the Values collection? What is the key then? I would try to access it by using
string scanOperator = documentData.Values["?scanOperator?"].Value;
Kofax's weird naming convention strikes again - during setup, said items are referred to as BatchVariableNames. However, during release they are KFX_REL_VARIABLEs (an enum named KfxLinkSourceType).
Here's how you can add all available items during setup:
foreach (var item in setupData.BatchVariableNames)
{
setupData.Links.Add(item, KfxLinkSourceType.KFX_REL_VARIABLE, item);
}
The following sample iterates over the DocumentData.Values collection, storing each BatchVariable in a Dictionary<string, string> named BatchVariables.
foreach (Value v in DocumentData.Values)
{
switch (v.SourceType)
{
case KfxLinkSourceType.KFX_REL_VARIABLE:
BatchVariables.Add(v.SourceName, v.Value);
break;
}
}
You can then access any of those variables by key - for example Scan Operator's User ID yields the scan user's domain and name.
1.i want to know whether i can make changes to the parmeter defined in the relationship.
what i want to do is to make a function with name of bookflight and then make changes to the number of seats if the flight is booked .
these are my cto files
namespace org.acme.airline.aircraft
/** Aircraft is an ACME Asset*/
asset Aircraft identified by aircraftId {
o String aircraftId
o Ownership ownershipType default="LEASED"
// Number of seats per class
o Integer firstClassSeats range = [4,]
o Integer businessClassSeats range = [6, 20]
o Integer economyClassSeats range = [30, ]
o String nickName optional
}
enum Ownership {
o LEASED
o OWNED
}
and for flight the code is
namespace org.acme.airline.flight
import org.acme.airline.aircraft.Aircraft
asset Flight identified by flightId {
// Solution to the exercise - try out the Regular expression at http://regex101.com
// Share your optimized regular expression with others :)
o String flightId regex=/[A-Z][A-Z][0-9][0-9][0-9]-[0-9][0-9]-[0-3][0-9]-[0-9][0-9]/
o String flightNumber
o Route route
o String[] aliasFlightNumber optional
--> Aircraft aircraft optional
}
concept Route {
o String origin regex=/[A-Z][A-Z][A-Z]/
o String destination regex=/[A-Z][A-Z][A-Z]/
o DateTime schedule
}
// Logistics department of ACME creates the flights
transaction CreateFlight {
o String flightNumber
o String origin
o String destination
o DateTime schedule
}
event FlightCreated {
o String flightId
}
// Assigns an aircraft to the flight
// The logistics / validation on availability of aircraft
// Kept outside of the Blockchain
transaction AssignAircraft {
o String flightId
o String aircraftId
}
// Event indicating that aircraft was assigned
event AircraftAssigned {
o String flightId
o String aircraftId
}
now what i want to make changes to reltionship in the flight
to make changes to it what should i do . i have made a javascript file.to
access make changes in it.
function booktickets(registry){
//array to recored the hold the instances of aircraft resourse
const bnDef = bnUtil.connection.getBusinessNetwork();
const factory = bnDef.getFactory();
let flightResource = factory.newResource(aircraftNamespace,aircraftType,'AE201-05-05-2020');
flightResource.setPropertyValue('flightNumber','AE101');
flightResource.route = factory.newConcept(aircraftNamespace,'Route');
flightResource.route.setPropertyValue('origin', 'DEL');
flightResource.route.setPropertyValue('destination' , 'APH');
flightResource.route.setPropertyValue('schedule' , new Date('2018-10-15T21:44Z'));
flightResource.aircraft = factory.newRelationship('org.acme.airline.aircraft', 'Aircraft', 'CRAFT01');
//.setPropertyValue()
flightResource.aircraft.setPropertyValue('ownershipType','LEASED');
flightResource.aircraft.setPropertyValue('firstClassSeats',10);
flightResource.aircraft.setPropertyValue('businessClassSeats',10);
flightResource.aircraft.setPropertyValue('economyClassSeats',100);
return registry.update(flightResource).then(()=>{
console.log('Successfully created the flight!!!');
bnUtil.disconnect();
}).catch((error)=>{
console.log(error);
bnUtil.disconnect();
});
}
your question appears to be: can you create a relationship from Flight (asset) to Aircraft (asset) in a transaction function (that operates in the chaincode runtime), and can you update the fields of the related Aircraft (in its separate registry). The answer is 'yes', you can, for both. You don't provide the model for the bookflight function, so can only make assumptions about its model definition. as a minimum (based on your code) it will need:
transaction bookflight { }
A code example of what you are trying to do with relationships - is shown here -> https://github.com/hyperledger/composer-sample-networks/blob/master/packages/perishable-network/lib/logic.js#L130
This section:
const bnDef = bnUtil.connection.getBusinessNetwork();
const factory = bnDef.getFactory();
is composer-client code - and will not work inside a transaction function (that is runtime code, you need to remove client code - the example below shows 'how' to do it.) Replace line 2 with :
const factory = getFactory();
See more on transaction functions, examples etc at https://hyperledger.github.io/composer/latest/reference/js_scripts
note: you can just assign values like:
flightResource.route.origin = 'DEL' ; // no need for.setPropertyValue('origin', 'DEL'); etc etc
I don't see your code to update the Aircraft registry (with flightResource.aircraft FYI) - but you would need that to update the fields in that related asset (presently, you're only updating the Flight registry above )
new Date() is non deterministic code - if you're hoping to achieve consensus from multiple peers/orgs.
You'll notice the link I sent earlier, shows the use of async/await rather than JS promises (.then etc etc) - easier to code, easier to read. cheers.
i have these two assets :
1]
asset bloodBankInformations identified by bloodBankId {
o String bloodBankId
o contact bloodBankContactDetails
--> bloodData bloodBankBloodData
}
2]
asset bloodData extends bloodBankInformations {
o String bloodDatakey
o bloodquotas bloodquota
}
now i want to query on this asset such that i can get data from both assets in one single query.
Composer Queries are run against a single Asset or Participant registry. There is no 'join' as you might see in a relational database.
However for your example it is possible to use a Filter on the REST server to filter the results (like a Query) and resolve the relationship of relationship fields.
Before showing you my example I wonder if you really wanted to 'extend' original asset? So I have simplified your model in my example - but the same principle works if you did intend to extend.
Model:
asset bloodBankInformations identified by bloodBankId {
o String bloodBankId
o contact bloodBankContactDetails
--> bloodData bloodBankBloodData
}
asset bloodData extends bloodBankInformations {
o String bloodDatakey
o bloodquotas bloodquota
}
Filter:
On the REST server used on GET on the endpoint /blookBankInformations
{"where":{"bloodBankId":"BB03"},"include":"resolve"}
My Response Body:
[
{
"$class": "org.acme.mynetwork.bloodBankInformations",
"bloodBankId": "BB03",
"bloodBankContactDetails": "Diferent address!",
"bloodBankBloodData": {
"$class": "org.acme.mynetwork.bloodData",
"bloodDatakey": "BL04",
"bloodquota": "Quota BBBB"
}
}
]
There is some additional information in the Composer Knowledge Wiki on filters.
Using Grails (or hibernate), I was wanting to know if there is a specific design pattern or method we should be using when implementing a SEARCH of our domain.
For example, on my website, I want to be able to filter(or search) by multiple properties in the domain.
EG: For I have a page which displays a list of HOTELS. When I submit a search form, or if a user clicks "filter by name='blah'", when I enter the controller I get the following:
Domain
String name
String location
Controller
if(params.name && params.reference) {
// Find name/reference
} else if(params.name) {
// Find name
} else if(params.reference) {
// Find reference
} else {
// Find all
}
As you can understand, if there are more properties in the domain to search/filter, the longer the controller gets.
Any help. Please note, I do not want to use the 'searchable' plugin, as this is too complex for my needs.
I would embed these in a named query in the Domain class itself. For example:
Class Hotel {
String name
String city
String country
boolean isNice
static namedQueries = {
customSearch { p ->
if (p?.name) eq('name', p.name)
if (p?.city) eq('name', p.city)
if (p?.country) eq('name', p.country)
if (p?.isNice != null) eq('isNice', p.isNice)
}
}
}
Then later in a controller somewhere ...
def results = Hotel.customSearch(params)
Of course this is a very simple example, but you can expand on it using the same named query or even adding others and chaining them together.