Hyperledger Composer Playground can not find my transaction function - hyperledger-composer

I am having issues trying to get my transactions working on Hyperledger composer playground.
I have a function called CastVote in my script.js file and a transaction called CastVote in my model file. Whenever I try to submit a transaction, it seems it can not find the CastVote function in my script file. I'm getting the below error:
Below is my code:
Model File:
namespace org.example.tasweetx
asset Vote identified by voteID {
o String voteID
o String voterID
o String candidateID
}
participant Voter identified by voterID {
o String voterID
o String voterFirstName
o String voterLastName
o String voterEmail
o String voterEmiratesID
}
participant Candidate identified by candidateID {
o String candidateID
o String candidateFirstName
o String candidateLastName
o Integer voteCount
}
transaction CastVote {
--> Voter voter
--> Candidate candidate
}
Script File:
/**
*
* #param {org.example.tasweetx.CastVote} transacation Function to handle vote casting and incrementing candidate vote count
* #transacation
*/
function CastVote(transacation) {
if(voter.voted == false) {
voter.voted == true;
IncrementVoteCount(transacation)
return getAssetRegistry('org.example.tasweetx.Candidate')
.then(function (assetRegistry){
return assetRegistry.update(voteCount);
})
} else {
throw new Error('You have already voted!');
}
}
function IncrementVoteCount(transacation) {
candidate.voteCount += 1;
return getAssetRegistry('org.example.tasweetx.Candidate')
.then(function (assetRegistry) {
return assetRegistry.update(voteCount);
})
}

you spelt transaction incorrectly, you have put
* #transacation
when it should be
* #transaction

Related

Hyperledger Composer Playground Setup Demo remove

I have a question. I'm working with Hyperledger Composer Playground and I'm using the transaction SetupDemo for tests. But right now everytime I run a test with the SetupDemo I have to delete the created participants and assets single handed.
Is there a possibility (a function or sth) to delete all of them at once?
Thanks for your help!!
yes I can add my code. I used the example "vehicle-manufacturer-lifecycle" as an example and now I'm changing the variable names.
This is my model file. The important part is the first part (with the first concept and asset)
namespace org.master
// BASE DEFINTIONS
concept MaterialDetails {
--> Manufacturer make
o String materialName
o String materialColour
o Double amount
}
asset Material identified by materialId {
o String materialId
o MaterialDetails materialDetails
--> Person owner optional
}
concept ModuleDetails {
--> Manufacturer make
o String moduleName
o Double amount
}
asset Module identified by moduleId {
o String moduleId
o ModuleDetails moduleDetails
--> Person owner optional
}
abstract participant Company identified by companyId {
o String companyId
o String name
}
participant Person identified by username {
o String username
o String email optional
}
// MANUFACTURE DEFINITIONS
participant Manufacturer extends Company {
}
participant Producer extends Company {
}
enum OrderStatus {
o PLACED
o SCHEDULED_FOR_MANUFACTURE
o VIN_ASSIGNED
o OWNER_ASSIGNED
o DELIVERED
}
concept Options {
o String trim
o String interior
o String[] extras
}
asset Order identified by orderId {
o String orderId
o MaterialDetails materialDetails
o OrderStatus orderStatus
o Options options
--> Person orderer
}
transaction PlaceOrder {
o String orderId
o MaterialDetails materialDetails
o Options options
--> Person orderer
}
event PlaceOrderEvent {
o String orderId
o MaterialDetails materialDetails
o Options options
--> Person orderer
}
transaction UpdateOrderStatus {
o OrderStatus orderStatus
o String vin optional
--> Order order
}
event UpdateOrderStatusEvent {
o OrderStatus orderStatus
o Order order
}
// REGULATOR DEFINITIONS
participant Regulator extends Company {
}
This is my script file:
// DEMO SETUP FUNCTIONS
/**
* Create the participants to use in the demo
* #param {org.master.SetupDemo} setupDemo - the SetupDemo transaction
* #transaction
*/
async function setupDemo() { // eslint-disable-line no-unused-vars
console.log('setupDemo');
const factory = getFactory();
const namespace = 'org.master';
let people = ['Paul'];
let materialSuppliers;
const materials = {
'MSLogistics': {
'Wire1': [
{
'materialId': 'W1',
'materialColour': 'Yellow',
'amount': 100
}
],
'Wire2': [
{
'materialId': 'W2',
'materialColour': 'Blue',
'amount': 100
}
],
'Wire3': [
{
'materialId': 'W3',
'materialColour': 'Black',
'amount': 100
}
]
},
'MSProduction': {
},
'MSQualityControl': {
}
};
// convert array names of people to be array of participant resources of type Person with identifier of that name
people = people.map(function (person) {
return factory.newResource(namespace, 'Person', person);
});
// create array of Manufacturer particpant resources identified by the top level keys in vehicles const
materialSuppliers = Object.keys(materials).map(function (manufacturer) {
const manufacturerResource = factory.newResource(namespace, 'Manufacturer', manufacturer);
manufacturerResource.name = manufacturer;
return manufacturerResource;
});
const regulator = factory.newResource(namespace, 'Regulator', 'VDA');
regulator.name = 'VDA';
// add the regulator
const regulatorRegistry = await getParticipantRegistry(namespace + '.Regulator');
await regulatorRegistry.add(regulator);
// add the manufacturers
const manufacturerRegistry = await getParticipantRegistry(namespace + '.Manufacturer');
await manufacturerRegistry.addAll(materialSuppliers);
// add the persons
const personRegistry = await getParticipantRegistry(namespace + '.Person');
await personRegistry.addAll(people);
// add the vehicles
const vehicleRegistry = await getAssetRegistry(namespace + '.Material');
const vehicleResources = [];
for (const manufacturer in materials) {
for (const model in materials[manufacturer]) {
const vehicconstemplatesForModel = materials[manufacturer][model];
vehicconstemplatesForModel.forEach(function(vehicconstemplate) {
const material = factory.newResource(namespace, 'Material', vehicconstemplate.materialId);
material.owner = people[vehicleResources.length+1];
material.materialDetails = factory.newConcept(namespace, 'MaterialDetails');
material.materialDetails.make = factory.newResource(namespace, 'Manufacturer', manufacturer);
material.materialDetails.materialName = model;
material.materialDetails.materialColour = vehicconstemplate.materialColour;
material.materialDetails.amount = vehicconstemplate.amount;
vehicleResources.push(material);
});
}
}
await vehicleRegistry.addAll(vehicleResources);
}
and this is the access control:
rule PersonMakeOrder {
description: "Allow Persons to create and view orders"
participant(p): "org.master.Person"
operation: CREATE
resource(o): "org.master.Order"
transaction(tx): "org.master.PlaceOrder"
condition: (o.orderer.getIdentifier() == p.getIdentifier())
action: ALLOW
}
rule PersonPlaceOrder {
description: "Allow Persons to place orders and view they've done this"
participant(p): "org.master.Person"
operation: CREATE, READ
resource(o): "org.master.PlaceOrder"
condition: (o.orderer.getIdentifier() == p.getIdentifier())
action: ALLOW
}
rule PersonReadOrder {
description: "Allow Persons to place orders and view they've done this"
participant(p): "org.master.Person"
operation: READ
resource(o): "org.master.Order"
condition: (o.orderer.getIdentifier() == p.getIdentifier())
action: ALLOW
}
rule ManufacturerUpdateOrder {
description: "Allow manufacturers to view and update their own orders"
participant(m): "org.master.Manufacturer"
operation: UPDATE
resource(o): "org.master.Order"
transaction(tx): "org.master.UpdateOrderStatus"
condition: (o.materialDetails.make.getIdentifier() == m.getIdentifier())
action: ALLOW
}
rule ManufacturerUpdateOrderStatus {
description: "Allow manufacturers to update order statuses and view they've done this"
participant(m): "org.master.Manufacturer"
operation: CREATE, READ
resource(o): "org.master.UpdateOrderStatus"
condition: (o.order.materialDetails.make.getIdentifier() == m.getIdentifier())
action: ALLOW
}
rule ManufacturerReadOrder {
description: "Allow manufacturers to view and update their own orders"
participant(m): "org.master.Manufacturer"
operation: READ
resource(o): "org.master.Order"
condition: (o.materialDetails.make.getIdentifier() == m.getIdentifier())
action: ALLOW
}
rule ManufacturerCreateVehicles {
description: "Allow manufacturers to create and view their vehicles"
participant(m): "org.master.Manufacturer"
operation: CREATE
resource(v): "org.master.Material"
transaction(tx): "org.master.UpdateOrderStatus"
condition: (v.materialDetails.make.getIdentifier() == m.getIdentifier() && tx.orderStatus == "VIN_ASSIGNED")
action: ALLOW
}
rule ManufacturerReadVehicles {
description: "Allow manufacturers to create and view their vehicles"
participant(m): "org.master.Manufacturer"
operation: READ
resource(v): "org.master.Material"
condition: (v.materialDetails.make.getIdentifier() == m.getIdentifier())
action: ALLOW
}
rule RegulatorAdminUser {
description: "Let the regulator do anything"
participant: "org.master.Regulator"
operation: ALL
resource: "**"
action: ALLOW
}
rule ParticipantsSeeSelves {
description: "Let participants see themselves"
participant(p): "org.hyperledger.composer.system.Participant"
operation: ALL
resource(r): "org.hyperledger.composer.system.Participant"
condition: (r.getIdentifier() == p.getIdentifier())
action: ALLOW
}
rule NetworkAdminUser {
description: "Grant business network administrators full access to user resources"
participant: "org.hyperledger.composer.system.NetworkAdmin"
operation: ALL
resource: "**"
action: ALLOW
}
rule System {
description: "Grant all full access to system resources"
participant: "org.**"
operation: ALL
resource: "org.hyperledger.composer.system.**"
action: ALLOW
}

Updating an asset in Composer

namespace com.biz
participant User identified by name {
o String name
}
participant Bank identified by name {
o String name
o Integer points
--> Document document optional
}
asset Document identified by docname {
o String docname
o String doctype
o String hash
o String from
o String to
}
transaction UploadDoc {
--> Document document
}
transaction ShareDoc {
--> Document document
--> Bank bank
}
transaction SetupDemo {
}
Script File :
/**
*
* #param {com.biz.UploadDoc} uploadDoc
* #transaction
*/
async function uploadDoc(uploadDoc) {
uploadDoc.document.docname = 'BC1.jpg';
uploadDoc.document.doctype = 'BC';
uploadDoc.document.hash = '123456';
uploadDoc.document.from = 'Bank_1';
uploadDoc.document.to = 'User_1';
const ar = await getAssetRegistry('com.biz.Document');
await ar.update(uploadDoc.document);
}
/**
*
* #param {com.biz.ShareDoc} shareDoc
* #transaction
*/
async function shareDoc(shareDoc) {
shareDoc.document.docname = 'BC1.jpg';
shareDoc.document.doctype = 'BC';
shareDoc.document.hash = '12346';
shareDoc.document.from = 'User_1';
shareDoc.document.to = shareDoc.bank.name;
const dr = await getAssetRegistry('com.biz.Document');
await dr.update(shareDoc.document);
}
/**
*
* #param {com.biz.SetupDemo} setupDemo
* #transaction
*/
async function setupDemo(setupDemo) {
const factory = getFactory();
const NS = 'com.biz';
const user = factory.newResource(NS,'User','User_1')
user.name='User_1';
const banks = [
factory.newResource(NS,'Bank','Bank_1'),
factory.newResource(NS,'Bank','Bank_2')
];
banks[0].name = 'Bank_1';
banks[1].name = 'Bank_2';
banks[0].points = 100;
banks[1].points = 100;
const userRegistry = await getParticipantRegistry(NS + '.User');
await userRegistry.addAll([user]);
const bankRegistry = await getParticipantRegistry(NS + '.Bank');
await bankRegistry.addAll(banks);
const documents = [
factory.newResource(NS, 'Document', 'Pa60.jpg'),
factory.newResource(NS, 'Document', 'Pa80.jpg')
];
documents[0].docname = 'Pa60.jpg';
documents[0].doctype = 'DrivingLicense';
documents[0].hash = '12345';
documents[0].from ='Bank_1';
documents[0].to = 'User_1';
documents[1].docname = 'Pa80.jpg';
documents[1].doctype = 'DrivingLicense';
documents[1].hash = '123456';
documents[1].from ='Bank_1';
documents[1].to = 'User_1';
const docRegistry = await getAssetRegistry(NS + '.Document')
await docRegistry.addAll(documents);
}
Issue : First I run transaction SetupDemo. Runs fine.
Next, I run transaction UploadDoc. Runs fine. Pa60.jpg is updated as BC1.jpg. ID given in Plyground for submitting transaction : Pa60.jpg
Next, I want to run ShareDoc transaction. If I give ID as BC1.jpg while submitting transaction, 'Object with id 'BC1.jpg' not found' error.
Please help me resolve the issue.

laravel Carbon calculate age at death (not till now)

get age till now() can use the code below
// Accessor for Age.
public function getAgeAttribute()
{
return Carbon::parse($this->attributes['birth_date'])->age;
}
but what about if the person is dead ?
in the database [death_date] field stored null or yyyy-mm-dd
so how to calculate the age between birth date ~ death date
// Accessor for Age.
public function getAgeAttribute()
{
if (!is_null($this->attributes['death_date']))
{
// how to calculate death_date - birth_date = realAge
return $realAge;
}
return Carbon::parse($this->attributes['birth_date'])->age;
}
just in case someone view this post, here is my answer
// Accessor for Age.
public function getAgeAttribute()
{
// return is_null($this->attributes['death_date'])
// ? Carbon::parse($this->attributes['birth_date'])->age
// : Carbon::parse($this->attributes['birth_date'])->diff(Carbon::parse($this->attributes['death_date']))->format('%y');
// oh, Carbon will auto convert NULL to now(), so no need the upper code
return Carbon::parse($this->attributes['birth_date'])->diff(Carbon::parse($this->attributes['death_date']))->format('%y');
}
you can solve it as the following:
public function getAgeAttribute()
{
if (!is_null($this->attributes['death_date']))
{
$realAge = Carbon::parse($this->attributes['death_date'])->diff(Carbon::parse($this->attributes['birth_date']))->format('%y');
return $realAge
}
return Carbon::parse($this->attributes['birth_date'])->age;
}
$birth_date = Carbon::parse($this->attributes['birth_date']);
$death_date = Carbon::parse($this->attributes['death_date']);
echo $birth_date->diffInYears($death_date);
Assuming you're looking for the age in years, try this:
$birth = new Carbon($this->attributes['birth_date']);
$death = new Carbon($this->attributes['death_date']);
$age = $birth->diffInYears($death); // Returns Integer

The method 'OrderBy' must be called before the method 'Skip' Exception

I was trying to implement the jQgrid using MvcjQgrid and i got this exception.
System.NotSupportedException was unhandled by user code
Message=The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.
Though OrdeyBy is used before Skip method why it is generating the exception? How can it be solved?
I encountered the exception in the controller:
public ActionResult GridDataBasic(GridSettings gridSettings)
{
var jobdescription = sm.GetJobDescription(gridSettings);
var totalJobDescription = sm.CountJobDescription(gridSettings);
var jsonData = new
{
total = totalJobDescription / gridSettings.PageSize + 1,
page = gridSettings.PageIndex,
records = totalJobDescription,
rows = (
from j in jobdescription
select new
{
id = j.JobDescriptionID,
cell = new[]
{
j.JobDescriptionID.ToString(),
j.JobTitle,
j.JobType.JobTypeName,
j.JobPriority.JobPriorityName,
j.JobType.Rate.ToString(),
j.CreationDate.ToShortDateString(),
j.JobDeadline.ToShortDateString(),
}
}).ToArray()
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
GetJobDescription Method and CountJobDescription Method
public int CountJobDescription(GridSettings gridSettings)
{
var jobdescription = _dataContext.JobDescriptions.AsQueryable();
if (gridSettings.IsSearch)
{
jobdescription = gridSettings.Where.rules.Aggregate(jobdescription, FilterJobDescription);
}
return jobdescription.Count();
}
public IQueryable<JobDescription> GetJobDescription(GridSettings gridSettings)
{
var jobdescription = orderJobDescription(_dataContext.JobDescriptions.AsQueryable(), gridSettings.SortColumn, gridSettings.SortOrder);
if (gridSettings.IsSearch)
{
jobdescription = gridSettings.Where.rules.Aggregate(jobdescription, FilterJobDescription);
}
return jobdescription.Skip((gridSettings.PageIndex - 1) * gridSettings.PageSize).Take(gridSettings.PageSize);
}
And Finally FilterJobDescription and OrderJobDescription
private static IQueryable<JobDescription> FilterJobDescription(IQueryable<JobDescription> jobdescriptions, Rule rule)
{
if (rule.field == "JobDescriptionID")
{
int result;
if (!int.TryParse(rule.data, out result))
return jobdescriptions;
return jobdescriptions.Where(j => j.JobDescriptionID == Convert.ToInt32(rule.data));
}
// Similar Statements
return jobdescriptions;
}
private IQueryable<JobDescription> orderJobDescription(IQueryable<JobDescription> jobdescriptions, string sortColumn, string sortOrder)
{
if (sortColumn == "JobDescriptionID")
return (sortOrder == "desc") ? jobdescriptions.OrderByDescending(j => j.JobDescriptionID) : jobdescriptions.OrderBy(j => j.JobDescriptionID);
return jobdescriptions;
}
The exception means that you always need a sorted input if you apply Skip, also in the case that the user doesn't click on a column to sort by. I could imagine that no sort column is specified when you open the grid view for the first time before the user can even click on a column header. To catch this case I would suggest to define some default sorting that you want when no other sorting criterion is given, for example:
switch (sortColumn)
{
case "JobDescriptionID":
return (sortOrder == "desc")
? jobdescriptions.OrderByDescending(j => j.JobDescriptionID)
: jobdescriptions.OrderBy(j => j.JobDescriptionID);
case "JobDescriptionTitle":
return (sortOrder == "desc")
? jobdescriptions.OrderByDescending(j => j.JobDescriptionTitle)
: jobdescriptions.OrderBy(j => j.JobDescriptionTitle);
// etc.
default:
return jobdescriptions.OrderBy(j => j.JobDescriptionID);
}
Edit
About your follow-up problems according to your comment: You cannot use ToString() in a LINQ to Entities query. And the next problem would be that you cannot create a string array in a query. I would suggest to load the data from the DB with their native types and then convert afterwards to strings (and to the string array) in memory:
rows = (from j in jobdescription
select new
{
JobDescriptionID = j.JobDescriptionID,
JobTitle = j.JobTitle,
JobTypeName = j.JobType.JobTypeName,
JobPriorityName = j.JobPriority.JobPriorityName,
Rate = j.JobType.Rate,
CreationDate = j.CreationDate,
JobDeadline = j.JobDeadline
})
.AsEnumerable() // DB query runs here, the rest is in memory
.Select(a => new
{
id = a.JobDescriptionID,
cell = new[]
{
a.JobDescriptionID.ToString(),
a.JobTitle,
a.JobTypeName,
a.JobPriorityName,
a.Rate.ToString(),
a.CreationDate.ToShortDateString(),
a.JobDeadline.ToShortDateString()
}
})
.ToArray()
I had the same type of problem after sorting using some code from Adam Anderson that accepted a generic sort string in OrderBy.
After getting this excpetion, i did lots of research and found that very clever fix:
var query = SelectOrders(companyNo, sortExpression);
return Queryable.Skip(query, iStartRow).Take(iPageSize).ToList();
Hope that helps !
SP

MVC3 ajaxgrid scaffolding error, Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Data.Objects.ObjectQuery'

I'm using MVC3 ajaxgrid scaffolding with EF4.1 code first and i've this error:
Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Data.Objects.ObjectQuery'
The code with the error in, is autogenerated:
public ActionResult GridData(int start = 0, int itemsPerPage = 20, string orderBy = "UserID", bool desc = false)
{
Response.AppendHeader("X-Total-Row-Count", repository.Users.Count().ToString());
ObjectQuery<User> users = (repository as IObjectContextAdapter).ObjectContext.CreateObjectSet<User>();
users = repository.Users.Include(u => u.Role); //ERROR HERE
users = users.OrderBy("it." + orderBy + (desc ? " desc" : ""));
return PartialView(users.Skip(start).Take(itemsPerPage));
}
This is the Users repository method and the Roles Foreign Key
public IQueryable<Entities.User> Users
{
get { return context.Users; }
}
public IQueryable<Entities.Role>Roles
{
get { return context.Roles; }
}
How can i resolve the conversion?
Get rid of the Lambda and use the related object:
var users = repository.Users.Include("Role"); //ERROR HERE
Assuming the entity User has a navigational property Role.
The reason is clear:
You have users variable with ObjectQuery<User> type then you assign that variable result of a query which is IQueryable<User>.
UPDATE:
Try the code below:
public ActionResult GridData(int start = 0, int itemsPerPage = 20, string orderBy = "UserID", bool desc = false)
{
Response.AppendHeader("X-Total-Row-Count", repository.Users.Count().ToString());
//ObjectQuery<User> users = (repository as IObjectContextAdapter).ObjectContext.CreateObjectSet<User>();
var users = repository.Users.Include(u => u.Role); //ERROR HERE
users = users.OrderBy("it." + orderBy + (desc ? " desc" : ""));
return PartialView(users.Skip(start).Take(itemsPerPage));
}

Resources