You need to sign in or sign up before continuing.
Select Git revision
CONTRIBUTING.md
-
Pierre Smeyers authoredPierre Smeyers authored
After you've reviewed these contribution guidelines, you'll be all set to
contribute to this project.
controller.go 4.97 KiB
/**
* controller.go
*
* COPYRIGHT: FUNDACIÓN TECNALIA RESEARCH & INNOVATION, 2022.
*/
package discard
import (
"errors"
"git.code.tecnalia.com/ledgerbuilder/sdk/core/api"
"git.code.tecnalia.com/ledgerbuilder/sdk/core/controller"
"git.code.tecnalia.com/ledgerbuilder/sdk/core/fabric/protos"
"git.code.tecnalia.com/ledgerbuilder/sdk/shared"
"git.code.tecnalia.com/blockchain/hypercog/controller/stats"
errs "git.code.tecnalia.com/traceblock/sdk/constants"
"git.code.tecnalia.com/traceblock/sdk/controller/base"
"git.code.tecnalia.com/traceblock/sdk/controller/split"
"git.code.tecnalia.com/traceblock/sdk/model"
)
type DiscardController struct {
base.TraceblockBaseController
}
var (
errInvalidInputData = errors.New("failed to read model")
errInvalidDiscardQuantity = errors.New("quantity to discard is greater than the available quantity")
)
// constructor like function
func NewDiscardController() *DiscardController {
ctl := new(DiscardController)
ctl.LowLevelController = controller.NewLowLevelController()
ctl.SetDataModelClosure(ctl.modelClosure)
return ctl
}
func (c DiscardController) modelClosure(stub shared.LedgerBuildrStubInterface) shared.LedgerBuildrAsset {
return NewDiscardParams()
}
func (c DiscardController) readTraceableAsset(stub shared.LedgerBuildrStubInterface, assetId string) (*model.TraceableAsset, error) {
readedModel, err := c.ReadAbstractAssetAndReturn(stub, assetId, model.NewTraceableAsset())
if err != nil {
return nil, err
}
// asset data successfully readed
asset, ok := readedModel.(*model.TraceableAsset)
if !ok {
return nil, errs.NotExistingAsset
}
return asset, nil
}
func (c DiscardController) readAsset(stub shared.LedgerBuildrStubInterface, requestAsset shared.LedgerBuildrAsset) (*model.TraceableAsset, error) {
return c.readTraceableAsset(stub, requestAsset.GetID())
}
// HyperCOG specific discard operation
func (c DiscardController) _discardAsset(stub shared.LedgerBuildrStubInterface, params *DiscardParams, discardableAsset *model.TraceableAsset) (*protos.Response, error) {
if discardableAsset.Quantity < params.Quantity {
return nil, errInvalidDiscardQuantity
}
var discardedStock *model.TraceableAsset
generatedIds := make([]string, 2)
if params.Quantity == discardableAsset.Quantity {
discardedStock = discardableAsset
} else {
// discardableAsset.Quantity > discardParams.Quantity
splitParams := new(split.SplitParams)
splitParams.SetID(discardableAsset.GetID())
splitParams.SplitConfig.ArchiveOld = true
splitParams.SplitConfig.Bidirectional = true
splitParams.SplitConfig.ChildCount = 2
splitParams.SplitConfig.BaseAsset.AssetType = discardableAsset.AssetType
splitParams.SplitConfig.BaseAsset.ArbitraryDataFields = discardableAsset.ArbitraryDataFields
subAssets, err := split.SplitAsset(c.TraceblockBaseController, stub, discardableAsset, *splitParams)
if err != nil {
return nil, err
}
for i, c := range subAssets {
generatedIds[i] = c.GetID()
}
newStock := subAssets[0]
newStock.Quantity = discardableAsset.Quantity - params.Quantity
newStock.Units = discardableAsset.Units
respNewStock:= c.SaveAbstractAsset(stub, &newStock)
if respNewStock.Status != shared.OK {
return &respNewStock, nil
}
discardedStock = &subAssets[1]
discardedStock.Quantity = params.Quantity
discardedStock.Units = discardableAsset.Units
discardedStock.Add("name", " Discarded")
}
err := stats.RegisterDiscard(stub, discardedStock.Quantity, discardedStock.Units)
if err != nil {
return nil, err
}
discardedStock.Add("status", "discarded")
// Already marked as modified
discardedStock.MarkAsDeleted()
respDiscarted := c.SaveAbstractAsset(stub, discardedStock)
if respDiscarted.Status != shared.OK {
return &respDiscarted, nil
}
ret := api.NewAPIGenericResponsePtr("DiscardController:Discard", nil, generatedIds).SendResponse()
return &ret, nil
}
func (c DiscardController) _archiveAsset(stub shared.LedgerBuildrStubInterface, params shared.LedgerBuildrAsset) (*protos.Response, error) {
discardParams, ok := params.(*DiscardParams)
if discardParams == nil || !ok {
//failed when casting/fetching input data
return nil, errInvalidInputData
}
discardableAsset, err := c.readAsset(stub, discardParams)
if err != nil {
return nil, err
}
status, ok := discardableAsset.Get("status")
if status != "stocked" || status == "stocked" && discardParams.Quantity == 0 {
// Done in MarkAssetAsDeleted middleware in normal operation
discardableAsset.MarkModification(stub)
discardableAsset.MarkAsDeleted()
responseArchive := c.DeleteAbstractAsset(stub, discardableAsset)
return &responseArchive, nil
}
// HyperCOG specific discard operation
return c._discardAsset(stub, discardParams, discardableAsset)
}
func (c DiscardController) Discard(stub shared.LedgerBuildrStubInterface, params shared.LedgerBuildrAsset) protos.Response {
ret, err := c._archiveAsset(stub, params)
if err != nil {
return api.NewApiResponsePtr("DiscardController:Discard", err, nil).SendResponse()
}
return *ret
}