Set up
This commit is contained in:
+61
-11
@@ -9,6 +9,7 @@ import (
|
|||||||
oclib "cloud.o-forge.io/core/oc-lib"
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
"cloud.o-forge.io/core/oc-lib/dbs"
|
"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/booking"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/peer"
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
beego "github.com/beego/beego/v2/server/web"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
@@ -21,41 +22,77 @@ type BookingController struct {
|
|||||||
|
|
||||||
var BookingExample booking.Booking
|
var BookingExample booking.Booking
|
||||||
|
|
||||||
|
// bookingDestFilter builds a dest_peer_id filter for booking queries.
|
||||||
|
// Default: filter by self (master's own bookings).
|
||||||
|
// With nanoID: verify the ID belongs to a NANO peer, then filter by it.
|
||||||
|
// Returns nil when nanoID is provided but does not resolve to a NANO peer
|
||||||
|
// (caller should return HTTP 404 or empty result).
|
||||||
|
func bookingDestFilter(nanoID string) *dbs.Filters {
|
||||||
|
targetID := ""
|
||||||
|
if nanoID != "" {
|
||||||
|
d := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).Search(&dbs.Filters{
|
||||||
|
And: map[string][]dbs.Filter{
|
||||||
|
"id": {{Operator: dbs.EQUAL.String(), Value: nanoID}},
|
||||||
|
"relation": {{Operator: dbs.EQUAL.String(), Value: peer.NANO}},
|
||||||
|
},
|
||||||
|
}, "", false, 0, 1)
|
||||||
|
if len(d.Data) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
targetID = nanoID
|
||||||
|
} else {
|
||||||
|
if self, err := oclib.GetMySelf(); err == nil && self != nil {
|
||||||
|
targetID = self.GetID()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if targetID == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &dbs.Filters{
|
||||||
|
And: map[string][]dbs.Filter{
|
||||||
|
"dest_peer_id": {{Operator: dbs.EQUAL.String(), Value: targetID}},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// @Title Search
|
// @Title Search
|
||||||
// @Description search bookings
|
// @Description search bookings
|
||||||
// @Param start_date path string true "the word search you want to get"
|
// @Param start_date path string true "the word search you want to get"
|
||||||
// @Param end_date path string true "the word search you want to get"
|
// @Param end_date path string true "the word search you want to get"
|
||||||
// @Param is_draft query string false "draft wished"
|
// @Param is_draft query string false "draft wished"
|
||||||
|
// @Param nano_id query string false "nano peer UUID — if set, return bookings for that nano instead of self"
|
||||||
// @Param offset query string false
|
// @Param offset query string false
|
||||||
// @Param limit query string false
|
// @Param limit query string false
|
||||||
// @Success 200 {workspace} models.workspace
|
// @Success 200 {workspace} models.workspace
|
||||||
// @router /search/:start_date/:end_date [get]
|
// @router /search/:start_date/:end_date [get]
|
||||||
func (o *BookingController) Search() {
|
func (o *BookingController) Search() {
|
||||||
|
|
||||||
/*
|
|
||||||
* This is a sample of how to use the search function
|
|
||||||
* The search function is used to search for data in the database
|
|
||||||
* The search function takes in a filter and a data type
|
|
||||||
* The filter is a struct that contains the search parameters
|
|
||||||
* The data type is an enum that specifies the type of data to search for
|
|
||||||
* The search function returns a list of data that matches the filter
|
|
||||||
* The data is then returned as a json object
|
|
||||||
*/
|
|
||||||
// store and return Id or post with UUID
|
|
||||||
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||||
offset, _ := strconv.Atoi(o.Ctx.Input.Query("offset"))
|
offset, _ := strconv.Atoi(o.Ctx.Input.Query("offset"))
|
||||||
limit, _ := strconv.Atoi(o.Ctx.Input.Query("limit"))
|
limit, _ := strconv.Atoi(o.Ctx.Input.Query("limit"))
|
||||||
start_date, _ := time.ParseInLocation("2006-01-02", o.Ctx.Input.Param(":start_date"), time.UTC)
|
start_date, _ := time.ParseInLocation("2006-01-02", o.Ctx.Input.Param(":start_date"), time.UTC)
|
||||||
end_date, _ := time.ParseInLocation("2006-01-02", o.Ctx.Input.Param(":end_date"), time.UTC)
|
end_date, _ := time.ParseInLocation("2006-01-02", o.Ctx.Input.Param(":end_date"), time.UTC)
|
||||||
isDraft := o.Ctx.Input.Query("is_draft")
|
isDraft := o.Ctx.Input.Query("is_draft")
|
||||||
|
nanoID := o.Ctx.Input.Query("nano_id")
|
||||||
sd := primitive.NewDateTimeFromTime(start_date)
|
sd := primitive.NewDateTimeFromTime(start_date)
|
||||||
ed := primitive.NewDateTimeFromTime(end_date)
|
ed := primitive.NewDateTimeFromTime(end_date)
|
||||||
fmt.Println("SEARCH START END", start_date, end_date)
|
fmt.Println("SEARCH START END", start_date, end_date)
|
||||||
|
df := bookingDestFilter(nanoID)
|
||||||
|
if nanoID != "" && df == nil {
|
||||||
|
o.Ctx.Output.SetStatus(http.StatusNotFound)
|
||||||
|
o.Data["json"] = map[string]string{"error": "nano peer not found: " + nanoID}
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
f := dbs.Filters{
|
f := dbs.Filters{
|
||||||
And: map[string][]dbs.Filter{
|
And: map[string][]dbs.Filter{
|
||||||
"expected_start_date": {{Operator: "gte", Value: sd}, {Operator: "lte", Value: ed}},
|
"expected_start_date": {{Operator: "gte", Value: sd}, {Operator: "lte", Value: ed}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if df != nil {
|
||||||
|
for k, v := range df.And {
|
||||||
|
f.And[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.BOOKING), user, peerID, groups, nil).Search(&f, "", isDraft == "true", int64(offset), int64(limit))
|
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.BOOKING), user, peerID, groups, nil).Search(&f, "", isDraft == "true", int64(offset), int64(limit))
|
||||||
o.ServeJSON()
|
o.ServeJSON()
|
||||||
}
|
}
|
||||||
@@ -63,6 +100,7 @@ func (o *BookingController) Search() {
|
|||||||
// @Title GetAll
|
// @Title GetAll
|
||||||
// @Description find booking by id
|
// @Description find booking by id
|
||||||
// @Param is_draft query string false "draft wished"
|
// @Param is_draft query string false "draft wished"
|
||||||
|
// @Param nano_id query string false "nano peer UUID — if set, return bookings for that nano instead of self"
|
||||||
// @Param offset query string false
|
// @Param offset query string false
|
||||||
// @Param limit query string false
|
// @Param limit query string false
|
||||||
// @Success 200 {booking} models.booking
|
// @Success 200 {booking} models.booking
|
||||||
@@ -72,7 +110,19 @@ func (o *BookingController) GetAll() {
|
|||||||
offset, _ := strconv.Atoi(o.Ctx.Input.Query("offset"))
|
offset, _ := strconv.Atoi(o.Ctx.Input.Query("offset"))
|
||||||
limit, _ := strconv.Atoi(o.Ctx.Input.Query("limit"))
|
limit, _ := strconv.Atoi(o.Ctx.Input.Query("limit"))
|
||||||
isDraft := o.Ctx.Input.Query("is_draft")
|
isDraft := o.Ctx.Input.Query("is_draft")
|
||||||
|
nanoID := o.Ctx.Input.Query("nano_id")
|
||||||
|
df := bookingDestFilter(nanoID)
|
||||||
|
if nanoID != "" && df == nil {
|
||||||
|
o.Ctx.Output.SetStatus(http.StatusNotFound)
|
||||||
|
o.Data["json"] = map[string]string{"error": "nano peer not found: " + nanoID}
|
||||||
|
o.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if df != nil {
|
||||||
|
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.BOOKING), user, peerID, groups, nil).Search(df, "", isDraft == "true", int64(offset), int64(limit))
|
||||||
|
} else {
|
||||||
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.BOOKING), user, peerID, groups, nil).LoadAll(isDraft == "true", int64(offset), int64(limit))
|
o.Data["json"] = oclib.NewRequest(oclib.LibDataEnum(oclib.BOOKING), user, peerID, groups, nil).LoadAll(isDraft == "true", int64(offset), int64(limit))
|
||||||
|
}
|
||||||
o.ServeJSON()
|
o.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ module oc-scheduler
|
|||||||
go 1.25.0
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260429050913-47d487ea8011
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260527135023-cef23b5f307b
|
||||||
github.com/beego/beego/v2 v2.3.8
|
github.com/beego/beego/v2 v2.3.8
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/robfig/cron v1.2.0
|
github.com/robfig/cron v1.2.0
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ cloud.o-forge.io/core/oc-lib v0.0.0-20260428065508-e3fbe7688ad5 h1:CVwlE1JgIcTAv
|
|||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260428065508-e3fbe7688ad5/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260428065508-e3fbe7688ad5/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260429050913-47d487ea8011 h1:owV5pQ+mS5xDCKEcGTO+BgsyYrKjkISL8LDsmjEb/3s=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260429050913-47d487ea8011 h1:owV5pQ+mS5xDCKEcGTO+BgsyYrKjkISL8LDsmjEb/3s=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20260429050913-47d487ea8011/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260429050913-47d487ea8011/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260527135023-cef23b5f307b h1:TWhmHeurbBmdyevREh4+mHWOBehO2AK587RCIjCfvOc=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20260527135023-cef23b5f307b/go.mod h1:JynnOb3eMr9VZW1mHq+Vsl3tzx6gPhPsGKpQD/dtEBc=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ func handleCreateResource(resp tools.NATSResponse) {
|
|||||||
if bk.FromNano != "" {
|
if bk.FromNano != "" {
|
||||||
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
pp := access.LoadOne(bk.FromNano)
|
pp := access.LoadOne(bk.FromNano)
|
||||||
if p := pp.ToPeer(); p == nil || p.Relation == peer.NANO {
|
if p := pp.ToPeer(); p == nil || p.Relation != peer.NANO {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
access = oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.BOOKING), nil)
|
access = oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.BOOKING), nil)
|
||||||
@@ -107,7 +107,7 @@ func handleCreateResource(resp tools.NATSResponse) {
|
|||||||
if pr.FromNano != "" {
|
if pr.FromNano != "" {
|
||||||
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
|
||||||
pp := access.LoadOne(pr.FromNano)
|
pp := access.LoadOne(pr.FromNano)
|
||||||
if p := pp.ToPeer(); p == nil || p.Relation == peer.NANO {
|
if p := pp.ToPeer(); p == nil || p.Relation != peer.NANO {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
access = oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PURCHASE_RESOURCE), nil)
|
access = oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PURCHASE_RESOURCE), nil)
|
||||||
|
|||||||
@@ -226,6 +226,8 @@ func (ws *WorkflowSchedule) GenerateExecutions(wf *workflow.Workflow, isPreempti
|
|||||||
SelectedPartnerships: ws.SelectedPartnerships,
|
SelectedPartnerships: ws.SelectedPartnerships,
|
||||||
SelectedBuyings: ws.SelectedBuyings,
|
SelectedBuyings: ws.SelectedBuyings,
|
||||||
SelectedStrategies: ws.SelectedStrategies,
|
SelectedStrategies: ws.SelectedStrategies,
|
||||||
|
SelectedPaymentMode: ws.SelectedPaymentType,
|
||||||
|
SelectedBillingStrategy: ws.SelectedBillingStrategy,
|
||||||
SelectedEmbeddedStorages: ws.SelectedEmbeddedStorages,
|
SelectedEmbeddedStorages: ws.SelectedEmbeddedStorages,
|
||||||
Priority: 1,
|
Priority: 1,
|
||||||
ExecutionsID: ws.UUID,
|
ExecutionsID: ws.UUID,
|
||||||
|
|||||||
@@ -356,6 +356,25 @@ func (s *SchedulingResourcesService) HandleCreateBooking(bk *booking.Booking, ad
|
|||||||
return !bk.IsDraft
|
return !bk.IsDraft
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Booking destined for a known NANO — store as local proxy without planner
|
||||||
|
// check (the resource belongs to the NANO, not us). oc-discovery will
|
||||||
|
// forward to the NANO via a DTN-critical stream.
|
||||||
|
if bk.DestPeerID != "" && bk.DestPeerID != self.GetID() {
|
||||||
|
d := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).Search(&dbs.Filters{
|
||||||
|
And: map[string][]dbs.Filter{
|
||||||
|
"id": {{Operator: dbs.EQUAL.String(), Value: bk.DestPeerID}},
|
||||||
|
"relation": {{Operator: dbs.EQUAL.String(), Value: peer.NANO}},
|
||||||
|
},
|
||||||
|
}, "", false, 0, 1)
|
||||||
|
if len(d.Data) > 0 {
|
||||||
|
bk.IsDraft = true
|
||||||
|
if stored, _, err := booking.NewAccessor(adminReq).StoreOne(bk); err == nil {
|
||||||
|
time.AfterFunc(10*time.Minute, func() { DraftTimeout(stored.GetID(), tools.BOOKING) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// New booking
|
// New booking
|
||||||
if !bk.ExpectedStartDate.IsZero() && bk.ExpectedStartDate.Before(time.Now().UTC()) {
|
if !bk.ExpectedStartDate.IsZero() && bk.ExpectedStartDate.Before(time.Now().UTC()) {
|
||||||
fmt.Println("HandleCreateBooking: start date in the past, discarding")
|
fmt.Println("HandleCreateBooking: start date in the past, discarding")
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"cloud.o-forge.io/core/oc-lib/dbs"
|
"cloud.o-forge.io/core/oc-lib/dbs"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/bill"
|
"cloud.o-forge.io/core/oc-lib/models/billing"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/booking"
|
"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/enum"
|
||||||
|
"cloud.o-forge.io/core/oc-lib/models/common/pricing"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/order"
|
"cloud.o-forge.io/core/oc-lib/models/order"
|
||||||
"cloud.o-forge.io/core/oc-lib/models/resources/purchase_resource"
|
"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/utils"
|
||||||
@@ -261,6 +262,7 @@ func GenerateOrder(
|
|||||||
ExecutionsID: executionsID,
|
ExecutionsID: executionsID,
|
||||||
Purchases: []*purchase_resource.PurchaseResource{},
|
Purchases: []*purchase_resource.PurchaseResource{},
|
||||||
Bookings: []*booking.Booking{},
|
Bookings: []*booking.Booking{},
|
||||||
|
Billing: map[pricing.BillingStrategy][]*booking.Booking{},
|
||||||
Status: enum.PENDING,
|
Status: enum.PENDING,
|
||||||
}
|
}
|
||||||
for _, purch := range purchases {
|
for _, purch := range purchases {
|
||||||
@@ -268,14 +270,17 @@ func GenerateOrder(
|
|||||||
scheduling_resources.FromSchedulerObject(tools.PURCHASE_RESOURCE, purch).(*purchase_resource.PurchaseResource))
|
scheduling_resources.FromSchedulerObject(tools.PURCHASE_RESOURCE, purch).(*purchase_resource.PurchaseResource))
|
||||||
}
|
}
|
||||||
for _, b := range bookings {
|
for _, b := range bookings {
|
||||||
newOrder.Bookings = append(newOrder.Bookings,
|
bk := scheduling_resources.FromSchedulerObject(tools.BOOKING, b).(*booking.Booking)
|
||||||
scheduling_resources.FromSchedulerObject(tools.BOOKING, b).(*booking.Booking))
|
newOrder.Bookings = append(newOrder.Bookings, bk)
|
||||||
|
// Groupe les bookings par stratégie de facturation pour permettre
|
||||||
|
// à DraftFirstBill de savoir quand et comment facturer chaque item.
|
||||||
|
newOrder.Billing[bk.BillingStrategy] = append(newOrder.Billing[bk.BillingStrategy], bk)
|
||||||
}
|
}
|
||||||
res, _, err := order.NewAccessor(request).StoreOne(newOrder)
|
res, _, err := order.NewAccessor(request).StoreOne(newOrder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if _, err := bill.DraftFirstBill(res.(*order.Order), request); err != nil {
|
if _, err := billing.DraftFirstBill(res.(*order.Order), request); err != nil {
|
||||||
return res.GetID(), err
|
return res.GetID(), err
|
||||||
}
|
}
|
||||||
return res.GetID(), nil
|
return res.GetID(), nil
|
||||||
|
|||||||
Reference in New Issue
Block a user