From c9ee2a1d247f0bb5795ec03523725943d74bc3e2 Mon Sep 17 00:00:00 2001 From: mr Date: Fri, 20 Jun 2025 09:05:44 +0200 Subject: [PATCH] add sets up --- entrypoint.go | 5 +- models/bill/bill.go | 317 +++++++++++++++++++++++++++++++++++++++++- models/order/order.go | 299 +-------------------------------------- 3 files changed, 325 insertions(+), 296 deletions(-) diff --git a/entrypoint.go b/entrypoint.go index 04124d2..7dc0d87 100644 --- a/entrypoint.go +++ b/entrypoint.go @@ -293,12 +293,13 @@ func (r *Request) DraftOrder(scheduler *workflow_execution.WorkflowSchedule) (*o } func (r *Request) PaymentTunnel(o *order.Order, scheduler *workflow_execution.WorkflowSchedule) error { - return o.Pay(scheduler, &tools.APIRequest{ + /*return o.Pay(scheduler, &tools.APIRequest{ Caller: r.caller, Username: r.user, PeerID: r.peerID, Groups: r.groups, - }) + })*/ + return nil } /* diff --git a/models/bill/bill.go b/models/bill/bill.go index 760fcc5..1919f9f 100644 --- a/models/bill/bill.go +++ b/models/bill/bill.go @@ -1,25 +1,338 @@ package bill import ( + "errors" + "fmt" + "sync" + "time" + + "cloud.o-forge.io/core/oc-lib/dbs" + "cloud.o-forge.io/core/oc-lib/models/booking" + "cloud.o-forge.io/core/oc-lib/models/common/enum" + "cloud.o-forge.io/core/oc-lib/models/common/pricing" + "cloud.o-forge.io/core/oc-lib/models/peer" + "cloud.o-forge.io/core/oc-lib/models/resources/purchase_resource" "cloud.o-forge.io/core/oc-lib/models/utils" + "cloud.o-forge.io/core/oc-lib/models/workflow_execution" "cloud.o-forge.io/core/oc-lib/tools" ) /* -* Bill is a struct that represents when emit billing +* Booking is a struct that represents a booking */ + type Bill struct { utils.AbstractObject + OrderID string `json:"order_id" bson:"order_id" validate:"required"` + OrderBy string `json:"order_by" bson:"order_by" validate:"required"` + WorkflowID string `json:"workflow_id" bson:"workflow_id" validate:"required"` + WorkflowExecutionIDs []string `json:"workflow_execution_ids" bson:"workflow_execution_ids" validate:"required"` + Status enum.CompletionStatus `json:"status" bson:"status" default:"0"` + SubOrders map[string]*PeerOrder `json:"sub_orders" bson:"sub_orders"` + Total float64 `json:"total" bson:"total" validate:"required"` } func (r *Bill) StoreDraftDefault() { r.IsDraft = true } +func (r *Bill) CanUpdate(set utils.DBObject) (bool, utils.DBObject) { + if !r.IsDraft && r.Status != set.(*Bill).Status { + return true, &Bill{Status: set.(*Bill).Status} // only state can be updated + } + return r.IsDraft, set +} + func (r *Bill) CanDelete() bool { - return r.IsDraft // only draft ComputeUnits can be deleted + return r.IsDraft // only draft order can be deleted +} + +func (o *Bill) DraftOrder(scheduler *workflow_execution.WorkflowSchedule, request *tools.APIRequest) error { + // set the draft order from the model + if err := o.draftStoreFromModel(scheduler, request); err != nil { + return err + } + return nil +} + +func (o *Bill) Pay(scheduler *workflow_execution.WorkflowSchedule, request *tools.APIRequest) error { + if _, err := o.draftBookOrder(scheduler, request); err != nil { + return err + } + o.Status = enum.PENDING + _, code, err := o.GetAccessor(request).UpdateOne(o, o.GetID()) + if code != 200 || err != nil { + return errors.New("could not update the order" + fmt.Sprintf("%v", err)) + } + if err := o.pay(request); err != nil { // pay the order + return err + } else { + o.IsDraft = false + } + for _, exec := range scheduler.WorkflowExecution { + exec.IsDraft = false + _, code, err := utils.GenericUpdateOne(exec, exec.GetID(), + workflow_execution.NewAccessor(request), &workflow_execution.WorkflowExecution{}) + if code != 200 || err != nil { + return errors.New("could not update the workflow execution" + fmt.Sprintf("%v", err)) + } + } + _, code, err = o.GetAccessor(request).UpdateOne(o, o.GetID()) + if code != 200 || err != nil { + return errors.New("could not update the order" + fmt.Sprintf("%v", err)) + } + /* + TODO : TEMPORARY SET BOOKINGS TO UNDRAFT TO AVOID DELETION + BUT NEXT ONLY WHO IS PAYED WILL BE ALLOWED TO CHANGE IT + */ + return nil +} + +func (o *Bill) draftStoreFromModel(scheduler *workflow_execution.WorkflowSchedule, request *tools.APIRequest) error { + if request == nil { + return errors.New("no request found") + } + fmt.Println("Drafting order", scheduler.Workflow) + if scheduler.Workflow == nil || scheduler.Workflow.Graph == nil { // if the workflow has no graph, return an error + return errors.New("no graph found") + } + o.SetName() + o.WorkflowID = scheduler.Workflow.GetID() + o.IsDraft = true + o.OrderBy = request.PeerID + o.WorkflowExecutionIDs = []string{} // create an array of ids + for _, exec := range scheduler.WorkflowExecution { + o.WorkflowExecutionIDs = append(o.WorkflowExecutionIDs, exec.GetID()) + } + // set the name of the order + resourcesByPeer := map[string][]pricing.PricedItemITF{} // create a map of resources by peer + + processings := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsProcessing, request, + int(scheduler.SelectedBuyingStrategy), scheduler.SelectedPricingStrategy) // get the processing items + datas := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsData, request, + int(scheduler.SelectedBuyingStrategy), scheduler.SelectedPricingStrategy) // get the data items + storages := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsStorage, request, + int(scheduler.SelectedBuyingStrategy), scheduler.SelectedPricingStrategy) // get the storage items + workflows := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsWorkflow, request, + int(scheduler.SelectedBuyingStrategy), scheduler.SelectedPricingStrategy) // get the workflow items + for _, items := range []map[string]pricing.PricedItemITF{processings, datas, storages, workflows} { + for _, item := range items { + if _, ok := resourcesByPeer[item.GetCreatorID()]; !ok { + resourcesByPeer[item.GetCreatorID()] = []pricing.PricedItemITF{} + } + resourcesByPeer[item.GetCreatorID()] = append(resourcesByPeer[item.GetCreatorID()], item) + } + } + for peerID, resources := range resourcesByPeer { + peerOrder := &PeerOrder{ + Status: enum.DRAFTED, + PeerID: peerID, + } + peerOrder.GenerateID() + for _, resource := range resources { + peerOrder.AddItem(resource, len(resources)) // TODO SPECIALS REF ADDITIONALS NOTES + } + if o.SubOrders == nil { + o.SubOrders = map[string]*PeerOrder{} + } + o.SubOrders[peerOrder.GetID()] = peerOrder + } + // search an order with same user name and same session id + err := o.SumUpBill(request) + if err != nil { + return err + } + // should store the order + res, code, err := o.GetAccessor(request).Search(&dbs.Filters{ + And: map[string][]dbs.Filter{ + "workflow_id": {{Operator: dbs.EQUAL.String(), Value: o.WorkflowID}}, + "order_by": {{Operator: dbs.EQUAL.String(), Value: request.PeerID}}, + }, + }, "", o.IsDraft) + if code != 200 || err != nil { + return errors.New("could not search the order" + fmt.Sprintf("%v", err)) + } + if len(res) > 0 { + _, code, err := utils.GenericUpdateOne(o, res[0].GetID(), o.GetAccessor(request), o) + if code != 200 || err != nil { + return errors.New("could not update the order" + fmt.Sprintf("%v", err)) + } + } else { + _, code, err := utils.GenericStoreOne(o, o.GetAccessor(request)) + if code != 200 || err != nil { + return errors.New("could not store the order" + fmt.Sprintf("%v", err)) + } + } + return nil +} + +func (o *Bill) draftBookOrder(scheduler *workflow_execution.WorkflowSchedule, request *tools.APIRequest) ([]*booking.Booking, error) { + draftedBookings := []*booking.Booking{} + if request == nil { + return draftedBookings, errors.New("no request found") + } + for _, exec := range scheduler.WorkflowExecution { + _, priceds, _, err := scheduler.Workflow.Planify(exec.ExecDate, exec.EndDate, request, + int(scheduler.SelectedBuyingStrategy), scheduler.SelectedPricingStrategy) + if err != nil { + return draftedBookings, errors.New("could not planify the workflow" + fmt.Sprintf("%v", err)) + } + bookings := exec.Book(scheduler.UUID, scheduler.Workflow.UUID, priceds) + for _, booking := range bookings { + _, err := (&peer.Peer{}).LaunchPeerExecution(booking.DestPeerID, "", + tools.BOOKING, tools.POST, booking.Serialize(booking), request.Caller) + if err != nil { + return draftedBookings, errors.New("could not launch the peer execution : " + fmt.Sprintf("%v", err)) + } + draftedBookings = append(draftedBookings, booking) + } + } + return draftedBookings, nil +} + +func (o *Bill) Quantity() int { + return len(o.WorkflowExecutionIDs) +} + +func (d *Bill) SetName() { + d.Name = d.UUID + "_order_" + "_" + time.Now().UTC().Format("2006-01-02T15:04:05") } func (d *Bill) GetAccessor(request *tools.APIRequest) utils.Accessor { return NewAccessor(request) // Create a new instance of the accessor } + +func (d *Bill) SumUpBill(request *tools.APIRequest) error { + for _, b := range d.SubOrders { + err := b.SumUpBill(request) + if err != nil { + return err + } + d.Total += b.Total + } + return nil +} + +// TO FINISH +func (d *Bill) pay(request *tools.APIRequest) error { + responses := make(chan *PeerOrder, len(d.SubOrders)) + var wg *sync.WaitGroup + wg.Add(len(d.SubOrders)) + for _, b := range d.SubOrders { + go b.Pay(request, responses, wg) + } + wg.Wait() + errs := "" + gotAnUnpaid := false + count := 0 + for range responses { + res := <-responses + count++ + if res != nil { + if res.Error != "" { + errs += res.Error + } + if res.Status != enum.PAID { + gotAnUnpaid = true + } + d.Status = enum.PARTIAL + d.SubOrders[res.GetID()] = res + if count == len(d.SubOrders) && !gotAnUnpaid { + d.Status = enum.PAID + } + } + } + + if errs != "" { + return errors.New(errs) + } + return nil +} + +type PeerOrder struct { + utils.AbstractObject + Error string `json:"error,omitempty" bson:"error,omitempty"` + PeerID string `json:"peer_id,omitempty" bson:"peer_id,omitempty"` + Status enum.CompletionStatus `json:"status" bson:"status" default:"0"` + BillingAddress string `json:"billing_address,omitempty" bson:"billing_address,omitempty"` + Items []*PeerItemOrder `json:"items,omitempty" bson:"items,omitempty"` + Total float64 `json:"total,omitempty" bson:"total,omitempty"` +} + +func (d *PeerOrder) Pay(request *tools.APIRequest, response chan *PeerOrder, wg *sync.WaitGroup) { + d.Status = enum.PENDING + go func() { + // DO SOMETHING TO PAY ON BLOCKCHAIN OR WHATEVER ON RETURN UPDATE STATUS + d.Status = enum.PAID // TO REMOVE LATER IT'S A MOCK + if d.Status == enum.PAID { + for _, b := range d.Items { + if !b.Item.IsPurchasable() { + continue + } + accessor := purchase_resource.NewAccessor(request) + accessor.StoreOne(&purchase_resource.PurchaseResource{ + ResourceID: b.Item.GetID(), + ResourceType: b.Item.GetType(), + EndDate: b.Item.GetLocationEnd(), + }) + } + } + + if d.Status != enum.PENDING { + response <- d + } + wg.Done() + }() +} + +func (d *PeerOrder) SumUpBill(request *tools.APIRequest) error { + for _, b := range d.Items { + tot, err := b.GetPrice(request) // missing something + if err != nil { + return err + } + d.Total += tot + } + return nil +} + +func (d *PeerOrder) AddItem(item pricing.PricedItemITF, quantity int) { + d.Items = append(d.Items, &PeerItemOrder{ + Quantity: quantity, + Item: item, + }) +} + +func (d *PeerOrder) SetName() { + d.Name = d.UUID + "_order_" + d.PeerID + "_" + time.Now().UTC().Format("2006-01-02T15:04:05") +} + +type PeerItemOrder struct { + Quantity int `json:"quantity,omitempty" bson:"quantity,omitempty"` + Purchase purchase_resource.PurchaseResource `json:"purchase,omitempty" bson:"purchase,omitempty"` + Item pricing.PricedItemITF `json:"item,omitempty" bson:"item,omitempty"` +} + +func (d *PeerItemOrder) GetPrice(request *tools.APIRequest) (float64, error) { + accessor := purchase_resource.NewAccessor(request) + search, code, _ := accessor.Search(&dbs.Filters{ + And: map[string][]dbs.Filter{ + "resource_id": {{Operator: dbs.EQUAL.String(), Value: d.Item.GetID()}}, + }, + }, "", d.Purchase.IsDraft) + if code == 200 && len(search) > 0 { + for _, s := range search { + if s.(*purchase_resource.PurchaseResource).EndDate == nil || time.Now().UTC().After(*s.(*purchase_resource.PurchaseResource).EndDate) { + return 0, nil + } + } + } + p, err := d.Item.GetPrice() + if err != nil { + return 0, err + } + return p * float64(d.Quantity), nil +} + +// WTF HOW TO SELECT THE RIGHT PRICE ??? +// SHOULD SET A BUYING STATUS WHEN PAYMENT IS VALIDATED diff --git a/models/order/order.go b/models/order/order.go index 1a90111..4d302c9 100644 --- a/models/order/order.go +++ b/models/order/order.go @@ -1,19 +1,12 @@ package order import ( - "errors" - "fmt" - "sync" "time" - "cloud.o-forge.io/core/oc-lib/dbs" "cloud.o-forge.io/core/oc-lib/models/booking" "cloud.o-forge.io/core/oc-lib/models/common/enum" - "cloud.o-forge.io/core/oc-lib/models/common/pricing" - "cloud.o-forge.io/core/oc-lib/models/peer" "cloud.o-forge.io/core/oc-lib/models/resources/purchase_resource" "cloud.o-forge.io/core/oc-lib/models/utils" - "cloud.o-forge.io/core/oc-lib/models/workflow_execution" "cloud.o-forge.io/core/oc-lib/tools" ) @@ -23,12 +16,12 @@ import ( type Order struct { utils.AbstractObject - OrderBy string `json:"order_by" bson:"order_by" validate:"required"` - WorkflowID string `json:"workflow_id" bson:"workflow_id" validate:"required"` - WorkflowExecutionIDs []string `json:"workflow_execution_ids" bson:"workflow_execution_ids" validate:"required"` - Status enum.CompletionStatus `json:"status" bson:"status" default:"0"` - SubOrders map[string]*PeerOrder `json:"sub_orders" bson:"sub_orders"` - Total float64 `json:"total" bson:"total" validate:"required"` + ExecutionsID string `json:"executions_id" bson:"executions_id" validate:"required"` + OrderBy string `json:"order_by" bson:"order_by" validate:"required"` + WorkflowID string `json:"workflow_id" bson:"workflow_id" validate:"required"` + Purchases []purchase_resource.PurchaseResource `json:"purchases" bson:"purchases"` + Bookings []booking.Booking `json:"bookings" bson:"bookings"` + Status enum.CompletionStatus `json:"status" bson:"status" default:"0"` } func (r *Order) StoreDraftDefault() { @@ -46,151 +39,8 @@ func (r *Order) CanDelete() bool { return r.IsDraft // only draft order can be deleted } -func (o *Order) DraftOrder(scheduler *workflow_execution.WorkflowSchedule, request *tools.APIRequest) error { - // set the draft order from the model - if err := o.draftStoreFromModel(scheduler, request); err != nil { - return err - } - return nil -} - -func (o *Order) Pay(scheduler *workflow_execution.WorkflowSchedule, request *tools.APIRequest) error { - if _, err := o.draftBookOrder(scheduler, request); err != nil { - return err - } - o.Status = enum.PENDING - _, code, err := o.GetAccessor(request).UpdateOne(o, o.GetID()) - if code != 200 || err != nil { - return errors.New("could not update the order" + fmt.Sprintf("%v", err)) - } - if err := o.pay(request); err != nil { // pay the order - return err - } else { - o.IsDraft = false - } - for _, exec := range scheduler.WorkflowExecution { - exec.IsDraft = false - _, code, err := utils.GenericUpdateOne(exec, exec.GetID(), - workflow_execution.NewAccessor(request), &workflow_execution.WorkflowExecution{}) - if code != 200 || err != nil { - return errors.New("could not update the workflow execution" + fmt.Sprintf("%v", err)) - } - } - _, code, err = o.GetAccessor(request).UpdateOne(o, o.GetID()) - if code != 200 || err != nil { - return errors.New("could not update the order" + fmt.Sprintf("%v", err)) - } - /* - TODO : TEMPORARY SET BOOKINGS TO UNDRAFT TO AVOID DELETION - BUT NEXT ONLY WHO IS PAYED WILL BE ALLOWED TO CHANGE IT - */ - return nil -} - -func (o *Order) draftStoreFromModel(scheduler *workflow_execution.WorkflowSchedule, request *tools.APIRequest) error { - if request == nil { - return errors.New("no request found") - } - fmt.Println("Drafting order", scheduler.Workflow) - if scheduler.Workflow == nil || scheduler.Workflow.Graph == nil { // if the workflow has no graph, return an error - return errors.New("no graph found") - } - o.SetName() - o.WorkflowID = scheduler.Workflow.GetID() - o.IsDraft = true - o.OrderBy = request.PeerID - o.WorkflowExecutionIDs = []string{} // create an array of ids - for _, exec := range scheduler.WorkflowExecution { - o.WorkflowExecutionIDs = append(o.WorkflowExecutionIDs, exec.GetID()) - } - // set the name of the order - resourcesByPeer := map[string][]pricing.PricedItemITF{} // create a map of resources by peer - - processings := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsProcessing, request, - int(scheduler.SelectedBuyingStrategy), scheduler.SelectedPricingStrategy) // get the processing items - datas := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsData, request, - int(scheduler.SelectedBuyingStrategy), scheduler.SelectedPricingStrategy) // get the data items - storages := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsStorage, request, - int(scheduler.SelectedBuyingStrategy), scheduler.SelectedPricingStrategy) // get the storage items - workflows := scheduler.Workflow.GetPricedItem(scheduler.Workflow.Graph.IsWorkflow, request, - int(scheduler.SelectedBuyingStrategy), scheduler.SelectedPricingStrategy) // get the workflow items - for _, items := range []map[string]pricing.PricedItemITF{processings, datas, storages, workflows} { - for _, item := range items { - if _, ok := resourcesByPeer[item.GetCreatorID()]; !ok { - resourcesByPeer[item.GetCreatorID()] = []pricing.PricedItemITF{} - } - resourcesByPeer[item.GetCreatorID()] = append(resourcesByPeer[item.GetCreatorID()], item) - } - } - for peerID, resources := range resourcesByPeer { - peerOrder := &PeerOrder{ - Status: enum.DRAFTED, - PeerID: peerID, - } - peerOrder.GenerateID() - for _, resource := range resources { - peerOrder.AddItem(resource, len(resources)) // TODO SPECIALS REF ADDITIONALS NOTES - } - if o.SubOrders == nil { - o.SubOrders = map[string]*PeerOrder{} - } - o.SubOrders[peerOrder.GetID()] = peerOrder - } - // search an order with same user name and same session id - err := o.SumUpBill(request) - if err != nil { - return err - } - // should store the order - res, code, err := o.GetAccessor(request).Search(&dbs.Filters{ - And: map[string][]dbs.Filter{ - "workflow_id": {{Operator: dbs.EQUAL.String(), Value: o.WorkflowID}}, - "order_by": {{Operator: dbs.EQUAL.String(), Value: request.PeerID}}, - }, - }, "", o.IsDraft) - if code != 200 || err != nil { - return errors.New("could not search the order" + fmt.Sprintf("%v", err)) - } - if len(res) > 0 { - _, code, err := utils.GenericUpdateOne(o, res[0].GetID(), o.GetAccessor(request), o) - if code != 200 || err != nil { - return errors.New("could not update the order" + fmt.Sprintf("%v", err)) - } - } else { - _, code, err := utils.GenericStoreOne(o, o.GetAccessor(request)) - if code != 200 || err != nil { - return errors.New("could not store the order" + fmt.Sprintf("%v", err)) - } - } - return nil -} - -func (o *Order) draftBookOrder(scheduler *workflow_execution.WorkflowSchedule, request *tools.APIRequest) ([]*booking.Booking, error) { - draftedBookings := []*booking.Booking{} - if request == nil { - return draftedBookings, errors.New("no request found") - } - for _, exec := range scheduler.WorkflowExecution { - _, priceds, _, err := scheduler.Workflow.Planify(exec.ExecDate, exec.EndDate, request, - int(scheduler.SelectedBuyingStrategy), scheduler.SelectedPricingStrategy) - if err != nil { - return draftedBookings, errors.New("could not planify the workflow" + fmt.Sprintf("%v", err)) - } - bookings := exec.Book(scheduler.UUID, scheduler.Workflow.UUID, priceds) - for _, booking := range bookings { - _, err := (&peer.Peer{}).LaunchPeerExecution(booking.DestPeerID, "", - tools.BOOKING, tools.POST, booking.Serialize(booking), request.Caller) - if err != nil { - return draftedBookings, errors.New("could not launch the peer execution : " + fmt.Sprintf("%v", err)) - } - draftedBookings = append(draftedBookings, booking) - } - } - return draftedBookings, nil -} - func (o *Order) Quantity() int { - return len(o.WorkflowExecutionIDs) + return len(o.Purchases) + len(o.Purchases) } func (d *Order) SetName() { @@ -200,138 +50,3 @@ func (d *Order) SetName() { func (d *Order) GetAccessor(request *tools.APIRequest) utils.Accessor { return NewAccessor(request) // Create a new instance of the accessor } - -func (d *Order) SumUpBill(request *tools.APIRequest) error { - for _, b := range d.SubOrders { - err := b.SumUpBill(request) - if err != nil { - return err - } - d.Total += b.Total - } - return nil -} - -// TO FINISH -func (d *Order) pay(request *tools.APIRequest) error { - responses := make(chan *PeerOrder, len(d.SubOrders)) - var wg *sync.WaitGroup - wg.Add(len(d.SubOrders)) - for _, b := range d.SubOrders { - go b.Pay(request, responses, wg) - } - wg.Wait() - errs := "" - gotAnUnpaid := false - count := 0 - for range responses { - res := <-responses - count++ - if res != nil { - if res.Error != "" { - errs += res.Error - } - if res.Status != enum.PAID { - gotAnUnpaid = true - } - d.Status = enum.PARTIAL - d.SubOrders[res.GetID()] = res - if count == len(d.SubOrders) && !gotAnUnpaid { - d.Status = enum.PAID - } - } - } - - if errs != "" { - return errors.New(errs) - } - return nil -} - -type PeerOrder struct { - utils.AbstractObject - Error string `json:"error,omitempty" bson:"error,omitempty"` - PeerID string `json:"peer_id,omitempty" bson:"peer_id,omitempty"` - Status enum.CompletionStatus `json:"status" bson:"status" default:"0"` - BillingAddress string `json:"billing_address,omitempty" bson:"billing_address,omitempty"` - Items []*PeerItemOrder `json:"items,omitempty" bson:"items,omitempty"` - Total float64 `json:"total,omitempty" bson:"total,omitempty"` -} - -func (d *PeerOrder) Pay(request *tools.APIRequest, response chan *PeerOrder, wg *sync.WaitGroup) { - d.Status = enum.PENDING - go func() { - // DO SOMETHING TO PAY ON BLOCKCHAIN OR WHATEVER ON RETURN UPDATE STATUS - d.Status = enum.PAID // TO REMOVE LATER IT'S A MOCK - if d.Status == enum.PAID { - for _, b := range d.Items { - if !b.Item.IsPurchasable() { - continue - } - accessor := purchase_resource.NewAccessor(request) - accessor.StoreOne(&purchase_resource.PurchaseResource{ - ResourceID: b.Item.GetID(), - ResourceType: b.Item.GetType(), - EndDate: b.Item.GetLocationEnd(), - }) - } - } - - if d.Status != enum.PENDING { - response <- d - } - wg.Done() - }() -} - -func (d *PeerOrder) SumUpBill(request *tools.APIRequest) error { - for _, b := range d.Items { - tot, err := b.GetPrice(request) // missing something - if err != nil { - return err - } - d.Total += tot - } - return nil -} - -func (d *PeerOrder) AddItem(item pricing.PricedItemITF, quantity int) { - d.Items = append(d.Items, &PeerItemOrder{ - Quantity: quantity, - Item: item, - }) -} - -func (d *PeerOrder) SetName() { - d.Name = d.UUID + "_order_" + d.PeerID + "_" + time.Now().UTC().Format("2006-01-02T15:04:05") -} - -type PeerItemOrder struct { - Quantity int `json:"quantity,omitempty" bson:"quantity,omitempty"` - Purchase purchase_resource.PurchaseResource `json:"purchase,omitempty" bson:"purchase,omitempty"` - Item pricing.PricedItemITF `json:"item,omitempty" bson:"item,omitempty"` -} - -func (d *PeerItemOrder) GetPrice(request *tools.APIRequest) (float64, error) { - accessor := purchase_resource.NewAccessor(request) - search, code, _ := accessor.Search(&dbs.Filters{ - And: map[string][]dbs.Filter{ - "resource_id": {{Operator: dbs.EQUAL.String(), Value: d.Item.GetID()}}, - }, - }, "", d.Purchase.IsDraft) - if code == 200 && len(search) > 0 { - for _, s := range search { - if s.(*purchase_resource.PurchaseResource).EndDate == nil || time.Now().UTC().After(*s.(*purchase_resource.PurchaseResource).EndDate) { - return 0, nil - } - } - } - p, err := d.Item.GetPrice() - if err != nil { - return 0, err - } - return p * float64(d.Quantity), nil -} - -// WTF HOW TO SELECT THE RIGHT PRICE ??? -// SHOULD SET A BUYING STATUS WHEN PAYMENT IS VALIDATED