diff --git a/docs/design/marketing-offer-program.md b/docs/design/marketing-offer-program.md index d67608129..d81a56f75 100644 --- a/docs/design/marketing-offer-program.md +++ b/docs/design/marketing-offer-program.md @@ -71,7 +71,7 @@ The credit is automatically applied to the account and will have a max limit tha redeemable_cap - integer num_redeemed - integer created_at - timestamp - offer_duration_days - int + expires_at - timestamp award_credit_duration_days - int invitee_credit_duration_days - int type - enum[FREE_TIER, REFERRAL] diff --git a/satellite/satellitedb/dbx/satellitedb.dbx b/satellite/satellitedb/dbx/satellitedb.dbx index 17ad9ebce..cb11ddbf8 100644 --- a/satellite/satellitedb/dbx/satellitedb.dbx +++ b/satellite/satellitedb/dbx/satellitedb.dbx @@ -570,3 +570,54 @@ read one ( where reset_password_token.owner_id = ? ) delete reset_password_token ( where reset_password_token.secret = ? ) + + +//--- offer table ---// + +model offer ( + key id + + field id serial + field name text ( updatable ) + field description text ( updatable ) + + // type has two possible value: FreeTier=1, Referral=2. + field type int ( updatable ) + + field credit_in_cents int ( updatable ) + field award_credit_duration_days int ( updatable ) + field invitee_credit_duration_days int ( updatable ) + + field redeemable_cap int ( updatable ) + field num_redeemed int ( updatable, autoinsert ) + + field expires_at timestamp ( updatable, autoinsert, nullable ) + field created_at timestamp ( autoinsert ) + + // status has three possible value: NoStatus=0, OnGoing=1, Expired=2. + field status int ( updatable, autoinsert ) +) + +read one ( + select offer + where offer.id = ? +) + +read one ( + select offer + where offer.status = ? + where offer.type = ? + where offer.expires_at >= ? +) + +read all ( select offer ) + +create offer ( ) + +update offer ( + where offer.id = ? + where offer.status = 0 + where offer.expires_at >= offer.created_at +) + +delete offer ( where offer.id = ? ) \ No newline at end of file diff --git a/satellite/satellitedb/dbx/satellitedb.dbx.go b/satellite/satellitedb/dbx/satellitedb.dbx.go index 30ea82c9b..708200868 100644 --- a/satellite/satellitedb/dbx/satellitedb.dbx.go +++ b/satellite/satellitedb/dbx/satellitedb.dbx.go @@ -388,6 +388,21 @@ CREATE TABLE nodes ( contained boolean NOT NULL, PRIMARY KEY ( id ) ); +CREATE TABLE offers ( + id serial NOT NULL, + name text NOT NULL, + description text NOT NULL, + type integer NOT NULL, + credit_in_cents integer NOT NULL, + award_credit_duration_days integer NOT NULL, + invitee_credit_duration_days integer NOT NULL, + redeemable_cap integer NOT NULL, + num_redeemed integer NOT NULL, + expires_at timestamp with time zone, + created_at timestamp with time zone NOT NULL, + status integer NOT NULL, + PRIMARY KEY ( id ) +); CREATE TABLE pending_audits ( node_id bytea NOT NULL, piece_id bytea NOT NULL, @@ -657,6 +672,21 @@ CREATE TABLE nodes ( contained INTEGER NOT NULL, PRIMARY KEY ( id ) ); +CREATE TABLE offers ( + id INTEGER NOT NULL, + name TEXT NOT NULL, + description TEXT NOT NULL, + type INTEGER NOT NULL, + credit_in_cents INTEGER NOT NULL, + award_credit_duration_days INTEGER NOT NULL, + invitee_credit_duration_days INTEGER NOT NULL, + redeemable_cap INTEGER NOT NULL, + num_redeemed INTEGER NOT NULL, + expires_at TIMESTAMP, + created_at TIMESTAMP NOT NULL, + status INTEGER NOT NULL, + PRIMARY KEY ( id ) +); CREATE TABLE pending_audits ( node_id BLOB NOT NULL, piece_id BLOB NOT NULL, @@ -2643,6 +2673,277 @@ func (f Node_Contained_Field) value() interface{} { func (Node_Contained_Field) _Column() string { return "contained" } +type Offer struct { + Id int + Name string + Description string + Type int + CreditInCents int + AwardCreditDurationDays int + InviteeCreditDurationDays int + RedeemableCap int + NumRedeemed int + ExpiresAt *time.Time + CreatedAt time.Time + Status int +} + +func (Offer) _Table() string { return "offers" } + +type Offer_Update_Fields struct { + Name Offer_Name_Field + Description Offer_Description_Field + Type Offer_Type_Field + CreditInCents Offer_CreditInCents_Field + AwardCreditDurationDays Offer_AwardCreditDurationDays_Field + InviteeCreditDurationDays Offer_InviteeCreditDurationDays_Field + RedeemableCap Offer_RedeemableCap_Field + NumRedeemed Offer_NumRedeemed_Field + ExpiresAt Offer_ExpiresAt_Field + Status Offer_Status_Field +} + +type Offer_Id_Field struct { + _set bool + _null bool + _value int +} + +func Offer_Id(v int) Offer_Id_Field { + return Offer_Id_Field{_set: true, _value: v} +} + +func (f Offer_Id_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_Id_Field) _Column() string { return "id" } + +type Offer_Name_Field struct { + _set bool + _null bool + _value string +} + +func Offer_Name(v string) Offer_Name_Field { + return Offer_Name_Field{_set: true, _value: v} +} + +func (f Offer_Name_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_Name_Field) _Column() string { return "name" } + +type Offer_Description_Field struct { + _set bool + _null bool + _value string +} + +func Offer_Description(v string) Offer_Description_Field { + return Offer_Description_Field{_set: true, _value: v} +} + +func (f Offer_Description_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_Description_Field) _Column() string { return "description" } + +type Offer_Type_Field struct { + _set bool + _null bool + _value int +} + +func Offer_Type(v int) Offer_Type_Field { + return Offer_Type_Field{_set: true, _value: v} +} + +func (f Offer_Type_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_Type_Field) _Column() string { return "type" } + +type Offer_CreditInCents_Field struct { + _set bool + _null bool + _value int +} + +func Offer_CreditInCents(v int) Offer_CreditInCents_Field { + return Offer_CreditInCents_Field{_set: true, _value: v} +} + +func (f Offer_CreditInCents_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_CreditInCents_Field) _Column() string { return "credit_in_cents" } + +type Offer_AwardCreditDurationDays_Field struct { + _set bool + _null bool + _value int +} + +func Offer_AwardCreditDurationDays(v int) Offer_AwardCreditDurationDays_Field { + return Offer_AwardCreditDurationDays_Field{_set: true, _value: v} +} + +func (f Offer_AwardCreditDurationDays_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_AwardCreditDurationDays_Field) _Column() string { return "award_credit_duration_days" } + +type Offer_InviteeCreditDurationDays_Field struct { + _set bool + _null bool + _value int +} + +func Offer_InviteeCreditDurationDays(v int) Offer_InviteeCreditDurationDays_Field { + return Offer_InviteeCreditDurationDays_Field{_set: true, _value: v} +} + +func (f Offer_InviteeCreditDurationDays_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_InviteeCreditDurationDays_Field) _Column() string { return "invitee_credit_duration_days" } + +type Offer_RedeemableCap_Field struct { + _set bool + _null bool + _value int +} + +func Offer_RedeemableCap(v int) Offer_RedeemableCap_Field { + return Offer_RedeemableCap_Field{_set: true, _value: v} +} + +func (f Offer_RedeemableCap_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_RedeemableCap_Field) _Column() string { return "redeemable_cap" } + +type Offer_NumRedeemed_Field struct { + _set bool + _null bool + _value int +} + +func Offer_NumRedeemed(v int) Offer_NumRedeemed_Field { + return Offer_NumRedeemed_Field{_set: true, _value: v} +} + +func (f Offer_NumRedeemed_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_NumRedeemed_Field) _Column() string { return "num_redeemed" } + +type Offer_ExpiresAt_Field struct { + _set bool + _null bool + _value *time.Time +} + +func Offer_ExpiresAt(v time.Time) Offer_ExpiresAt_Field { + return Offer_ExpiresAt_Field{_set: true, _value: &v} +} + +func Offer_ExpiresAt_Raw(v *time.Time) Offer_ExpiresAt_Field { + if v == nil { + return Offer_ExpiresAt_Null() + } + return Offer_ExpiresAt(*v) +} + +func Offer_ExpiresAt_Null() Offer_ExpiresAt_Field { + return Offer_ExpiresAt_Field{_set: true, _null: true} +} + +func (f Offer_ExpiresAt_Field) isnull() bool { return !f._set || f._null || f._value == nil } + +func (f Offer_ExpiresAt_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_ExpiresAt_Field) _Column() string { return "expires_at" } + +type Offer_CreatedAt_Field struct { + _set bool + _null bool + _value time.Time +} + +func Offer_CreatedAt(v time.Time) Offer_CreatedAt_Field { + return Offer_CreatedAt_Field{_set: true, _value: v} +} + +func (f Offer_CreatedAt_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_CreatedAt_Field) _Column() string { return "created_at" } + +type Offer_Status_Field struct { + _set bool + _null bool + _value int +} + +func Offer_Status(v int) Offer_Status_Field { + return Offer_Status_Field{_set: true, _value: v} +} + +func (f Offer_Status_Field) value() interface{} { + if !f._set || f._null { + return nil + } + return f._value +} + +func (Offer_Status_Field) _Column() string { return "status" } + type PendingAudits struct { NodeId []byte PieceId []byte @@ -4468,6 +4769,43 @@ func (obj *postgresImpl) Create_ResetPasswordToken(ctx context.Context, } +func (obj *postgresImpl) Create_Offer(ctx context.Context, + offer_name Offer_Name_Field, + offer_description Offer_Description_Field, + offer_type Offer_Type_Field, + offer_credit_in_cents Offer_CreditInCents_Field, + offer_award_credit_duration_days Offer_AwardCreditDurationDays_Field, + offer_invitee_credit_duration_days Offer_InviteeCreditDurationDays_Field, + offer_redeemable_cap Offer_RedeemableCap_Field) ( + offer *Offer, err error) { + + __now := obj.db.Hooks.Now().UTC() + __name_val := offer_name.value() + __description_val := offer_description.value() + __type_val := offer_type.value() + __credit_in_cents_val := offer_credit_in_cents.value() + __award_credit_duration_days_val := offer_award_credit_duration_days.value() + __invitee_credit_duration_days_val := offer_invitee_credit_duration_days.value() + __redeemable_cap_val := offer_redeemable_cap.value() + __num_redeemed_val := int(0) + __expires_at_val := (*time.Time)(nil) + __created_at_val := __now + __status_val := int(0) + + var __embed_stmt = __sqlbundle_Literal("INSERT INTO offers ( name, description, type, credit_in_cents, award_credit_duration_days, invitee_credit_duration_days, redeemable_cap, num_redeemed, expires_at, created_at, status ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) RETURNING offers.id, offers.name, offers.description, offers.type, offers.credit_in_cents, offers.award_credit_duration_days, offers.invitee_credit_duration_days, offers.redeemable_cap, offers.num_redeemed, offers.expires_at, offers.created_at, offers.status") + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __name_val, __description_val, __type_val, __credit_in_cents_val, __award_credit_duration_days_val, __invitee_credit_duration_days_val, __redeemable_cap_val, __num_redeemed_val, __expires_at_val, __created_at_val, __status_val) + + offer = &Offer{} + err = obj.driver.QueryRow(__stmt, __name_val, __description_val, __type_val, __credit_in_cents_val, __award_credit_duration_days_val, __invitee_credit_duration_days_val, __redeemable_cap_val, __num_redeemed_val, __expires_at_val, __created_at_val, __status_val).Scan(&offer.Id, &offer.Name, &offer.Description, &offer.Type, &offer.CreditInCents, &offer.AwardCreditDurationDays, &offer.InviteeCreditDurationDays, &offer.RedeemableCap, &offer.NumRedeemed, &offer.ExpiresAt, &offer.CreatedAt, &offer.Status) + if err != nil { + return nil, obj.makeErr(err) + } + return offer, nil + +} + func (obj *postgresImpl) Get_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field) ( pending_audits *PendingAudits, err error) { @@ -5501,6 +5839,104 @@ func (obj *postgresImpl) Get_ResetPasswordToken_By_OwnerId(ctx context.Context, } +func (obj *postgresImpl) Get_Offer_By_Id(ctx context.Context, + offer_id Offer_Id_Field) ( + offer *Offer, err error) { + + var __embed_stmt = __sqlbundle_Literal("SELECT offers.id, offers.name, offers.description, offers.type, offers.credit_in_cents, offers.award_credit_duration_days, offers.invitee_credit_duration_days, offers.redeemable_cap, offers.num_redeemed, offers.expires_at, offers.created_at, offers.status FROM offers WHERE offers.id = ?") + + var __values []interface{} + __values = append(__values, offer_id.value()) + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __values...) + + offer = &Offer{} + err = obj.driver.QueryRow(__stmt, __values...).Scan(&offer.Id, &offer.Name, &offer.Description, &offer.Type, &offer.CreditInCents, &offer.AwardCreditDurationDays, &offer.InviteeCreditDurationDays, &offer.RedeemableCap, &offer.NumRedeemed, &offer.ExpiresAt, &offer.CreatedAt, &offer.Status) + if err != nil { + return nil, obj.makeErr(err) + } + return offer, nil + +} + +func (obj *postgresImpl) Get_Offer_By_Status_And_Type_And_ExpiresAt_GreaterOrEqual(ctx context.Context, + offer_status Offer_Status_Field, + offer_type Offer_Type_Field, + offer_expires_at_greater_or_equal Offer_ExpiresAt_Field) ( + offer *Offer, err error) { + + var __embed_stmt = __sqlbundle_Literal("SELECT offers.id, offers.name, offers.description, offers.type, offers.credit_in_cents, offers.award_credit_duration_days, offers.invitee_credit_duration_days, offers.redeemable_cap, offers.num_redeemed, offers.expires_at, offers.created_at, offers.status FROM offers WHERE offers.status = ? AND offers.type = ? AND offers.expires_at >= ? LIMIT 2") + + var __values []interface{} + __values = append(__values, offer_status.value(), offer_type.value(), offer_expires_at_greater_or_equal.value()) + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __values...) + + __rows, err := obj.driver.Query(__stmt, __values...) + if err != nil { + return nil, obj.makeErr(err) + } + defer __rows.Close() + + if !__rows.Next() { + if err := __rows.Err(); err != nil { + return nil, obj.makeErr(err) + } + return nil, makeErr(sql.ErrNoRows) + } + + offer = &Offer{} + err = __rows.Scan(&offer.Id, &offer.Name, &offer.Description, &offer.Type, &offer.CreditInCents, &offer.AwardCreditDurationDays, &offer.InviteeCreditDurationDays, &offer.RedeemableCap, &offer.NumRedeemed, &offer.ExpiresAt, &offer.CreatedAt, &offer.Status) + if err != nil { + return nil, obj.makeErr(err) + } + + if __rows.Next() { + return nil, tooManyRows("Offer_By_Status_And_Type_And_ExpiresAt_GreaterOrEqual") + } + + if err := __rows.Err(); err != nil { + return nil, obj.makeErr(err) + } + + return offer, nil + +} + +func (obj *postgresImpl) All_Offer(ctx context.Context) ( + rows []*Offer, err error) { + + var __embed_stmt = __sqlbundle_Literal("SELECT offers.id, offers.name, offers.description, offers.type, offers.credit_in_cents, offers.award_credit_duration_days, offers.invitee_credit_duration_days, offers.redeemable_cap, offers.num_redeemed, offers.expires_at, offers.created_at, offers.status FROM offers") + + var __values []interface{} + __values = append(__values) + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __values...) + + __rows, err := obj.driver.Query(__stmt, __values...) + if err != nil { + return nil, obj.makeErr(err) + } + defer __rows.Close() + + for __rows.Next() { + offer := &Offer{} + err = __rows.Scan(&offer.Id, &offer.Name, &offer.Description, &offer.Type, &offer.CreditInCents, &offer.AwardCreditDurationDays, &offer.InviteeCreditDurationDays, &offer.RedeemableCap, &offer.NumRedeemed, &offer.ExpiresAt, &offer.CreatedAt, &offer.Status) + if err != nil { + return nil, obj.makeErr(err) + } + rows = append(rows, offer) + } + if err := __rows.Err(); err != nil { + return nil, obj.makeErr(err) + } + return rows, nil + +} + func (obj *postgresImpl) Update_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field, update PendingAudits_Update_Fields) ( @@ -6008,6 +6444,91 @@ func (obj *postgresImpl) Update_RegistrationToken_By_Secret(ctx context.Context, return registration_token, nil } +func (obj *postgresImpl) Update_Offer_By_Id_And_Status_Equal_Number_And_ExpiresAt_GreaterOrEqual_CreatedAt(ctx context.Context, + offer_id Offer_Id_Field, + update Offer_Update_Fields) ( + offer *Offer, err error) { + var __sets = &__sqlbundle_Hole{} + + var __embed_stmt = __sqlbundle_Literals{Join: "", SQLs: []__sqlbundle_SQL{__sqlbundle_Literal("UPDATE offers SET "), __sets, __sqlbundle_Literal(" WHERE offers.id = ? AND offers.status = 0 AND offers.expires_at >= offers.created_at RETURNING offers.id, offers.name, offers.description, offers.type, offers.credit_in_cents, offers.award_credit_duration_days, offers.invitee_credit_duration_days, offers.redeemable_cap, offers.num_redeemed, offers.expires_at, offers.created_at, offers.status")}} + + __sets_sql := __sqlbundle_Literals{Join: ", "} + var __values []interface{} + var __args []interface{} + + if update.Name._set { + __values = append(__values, update.Name.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("name = ?")) + } + + if update.Description._set { + __values = append(__values, update.Description.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("description = ?")) + } + + if update.Type._set { + __values = append(__values, update.Type.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("type = ?")) + } + + if update.CreditInCents._set { + __values = append(__values, update.CreditInCents.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("credit_in_cents = ?")) + } + + if update.AwardCreditDurationDays._set { + __values = append(__values, update.AwardCreditDurationDays.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("award_credit_duration_days = ?")) + } + + if update.InviteeCreditDurationDays._set { + __values = append(__values, update.InviteeCreditDurationDays.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("invitee_credit_duration_days = ?")) + } + + if update.RedeemableCap._set { + __values = append(__values, update.RedeemableCap.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("redeemable_cap = ?")) + } + + if update.NumRedeemed._set { + __values = append(__values, update.NumRedeemed.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("num_redeemed = ?")) + } + + if update.ExpiresAt._set { + __values = append(__values, update.ExpiresAt.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("expires_at = ?")) + } + + if update.Status._set { + __values = append(__values, update.Status.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("status = ?")) + } + + if len(__sets_sql.SQLs) == 0 { + return nil, emptyUpdate() + } + + __args = append(__args, offer_id.value()) + + __values = append(__values, __args...) + __sets.SQL = __sets_sql + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __values...) + + offer = &Offer{} + err = obj.driver.QueryRow(__stmt, __values...).Scan(&offer.Id, &offer.Name, &offer.Description, &offer.Type, &offer.CreditInCents, &offer.AwardCreditDurationDays, &offer.InviteeCreditDurationDays, &offer.RedeemableCap, &offer.NumRedeemed, &offer.ExpiresAt, &offer.CreatedAt, &offer.Status) + if err == sql.ErrNoRows { + return nil, nil + } + if err != nil { + return nil, obj.makeErr(err) + } + return offer, nil +} + func (obj *postgresImpl) Delete_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field) ( deleted bool, err error) { @@ -6347,6 +6868,32 @@ func (obj *postgresImpl) Delete_ResetPasswordToken_By_Secret(ctx context.Context } +func (obj *postgresImpl) Delete_Offer_By_Id(ctx context.Context, + offer_id Offer_Id_Field) ( + deleted bool, err error) { + + var __embed_stmt = __sqlbundle_Literal("DELETE FROM offers WHERE offers.id = ?") + + var __values []interface{} + __values = append(__values, offer_id.value()) + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __values...) + + __res, err := obj.driver.Exec(__stmt, __values...) + if err != nil { + return false, obj.makeErr(err) + } + + __count, err := __res.RowsAffected() + if err != nil { + return false, obj.makeErr(err) + } + + return __count > 0, nil + +} + func (impl postgresImpl) isConstraintError(err error) ( constraint string, ok bool) { if e, ok := err.(*pq.Error); ok { @@ -6465,6 +7012,16 @@ func (obj *postgresImpl) deleteAll(ctx context.Context) (count int64, err error) return 0, obj.makeErr(err) } + __count, err = __res.RowsAffected() + if err != nil { + return 0, obj.makeErr(err) + } + count += __count + __res, err = obj.driver.Exec("DELETE FROM offers;") + if err != nil { + return 0, obj.makeErr(err) + } + __count, err = __res.RowsAffected() if err != nil { return 0, obj.makeErr(err) @@ -7133,6 +7690,46 @@ func (obj *sqlite3Impl) Create_ResetPasswordToken(ctx context.Context, } +func (obj *sqlite3Impl) Create_Offer(ctx context.Context, + offer_name Offer_Name_Field, + offer_description Offer_Description_Field, + offer_type Offer_Type_Field, + offer_credit_in_cents Offer_CreditInCents_Field, + offer_award_credit_duration_days Offer_AwardCreditDurationDays_Field, + offer_invitee_credit_duration_days Offer_InviteeCreditDurationDays_Field, + offer_redeemable_cap Offer_RedeemableCap_Field) ( + offer *Offer, err error) { + + __now := obj.db.Hooks.Now().UTC() + __name_val := offer_name.value() + __description_val := offer_description.value() + __type_val := offer_type.value() + __credit_in_cents_val := offer_credit_in_cents.value() + __award_credit_duration_days_val := offer_award_credit_duration_days.value() + __invitee_credit_duration_days_val := offer_invitee_credit_duration_days.value() + __redeemable_cap_val := offer_redeemable_cap.value() + __num_redeemed_val := int(0) + __expires_at_val := (*time.Time)(nil) + __created_at_val := __now + __status_val := int(0) + + var __embed_stmt = __sqlbundle_Literal("INSERT INTO offers ( name, description, type, credit_in_cents, award_credit_duration_days, invitee_credit_duration_days, redeemable_cap, num_redeemed, expires_at, created_at, status ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )") + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __name_val, __description_val, __type_val, __credit_in_cents_val, __award_credit_duration_days_val, __invitee_credit_duration_days_val, __redeemable_cap_val, __num_redeemed_val, __expires_at_val, __created_at_val, __status_val) + + __res, err := obj.driver.Exec(__stmt, __name_val, __description_val, __type_val, __credit_in_cents_val, __award_credit_duration_days_val, __invitee_credit_duration_days_val, __redeemable_cap_val, __num_redeemed_val, __expires_at_val, __created_at_val, __status_val) + if err != nil { + return nil, obj.makeErr(err) + } + __pk, err := __res.LastInsertId() + if err != nil { + return nil, obj.makeErr(err) + } + return obj.getLastOffer(ctx, __pk) + +} + func (obj *sqlite3Impl) Get_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field) ( pending_audits *PendingAudits, err error) { @@ -8166,6 +8763,104 @@ func (obj *sqlite3Impl) Get_ResetPasswordToken_By_OwnerId(ctx context.Context, } +func (obj *sqlite3Impl) Get_Offer_By_Id(ctx context.Context, + offer_id Offer_Id_Field) ( + offer *Offer, err error) { + + var __embed_stmt = __sqlbundle_Literal("SELECT offers.id, offers.name, offers.description, offers.type, offers.credit_in_cents, offers.award_credit_duration_days, offers.invitee_credit_duration_days, offers.redeemable_cap, offers.num_redeemed, offers.expires_at, offers.created_at, offers.status FROM offers WHERE offers.id = ?") + + var __values []interface{} + __values = append(__values, offer_id.value()) + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __values...) + + offer = &Offer{} + err = obj.driver.QueryRow(__stmt, __values...).Scan(&offer.Id, &offer.Name, &offer.Description, &offer.Type, &offer.CreditInCents, &offer.AwardCreditDurationDays, &offer.InviteeCreditDurationDays, &offer.RedeemableCap, &offer.NumRedeemed, &offer.ExpiresAt, &offer.CreatedAt, &offer.Status) + if err != nil { + return nil, obj.makeErr(err) + } + return offer, nil + +} + +func (obj *sqlite3Impl) Get_Offer_By_Status_And_Type_And_ExpiresAt_GreaterOrEqual(ctx context.Context, + offer_status Offer_Status_Field, + offer_type Offer_Type_Field, + offer_expires_at_greater_or_equal Offer_ExpiresAt_Field) ( + offer *Offer, err error) { + + var __embed_stmt = __sqlbundle_Literal("SELECT offers.id, offers.name, offers.description, offers.type, offers.credit_in_cents, offers.award_credit_duration_days, offers.invitee_credit_duration_days, offers.redeemable_cap, offers.num_redeemed, offers.expires_at, offers.created_at, offers.status FROM offers WHERE offers.status = ? AND offers.type = ? AND offers.expires_at >= ? LIMIT 2") + + var __values []interface{} + __values = append(__values, offer_status.value(), offer_type.value(), offer_expires_at_greater_or_equal.value()) + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __values...) + + __rows, err := obj.driver.Query(__stmt, __values...) + if err != nil { + return nil, obj.makeErr(err) + } + defer __rows.Close() + + if !__rows.Next() { + if err := __rows.Err(); err != nil { + return nil, obj.makeErr(err) + } + return nil, makeErr(sql.ErrNoRows) + } + + offer = &Offer{} + err = __rows.Scan(&offer.Id, &offer.Name, &offer.Description, &offer.Type, &offer.CreditInCents, &offer.AwardCreditDurationDays, &offer.InviteeCreditDurationDays, &offer.RedeemableCap, &offer.NumRedeemed, &offer.ExpiresAt, &offer.CreatedAt, &offer.Status) + if err != nil { + return nil, obj.makeErr(err) + } + + if __rows.Next() { + return nil, tooManyRows("Offer_By_Status_And_Type_And_ExpiresAt_GreaterOrEqual") + } + + if err := __rows.Err(); err != nil { + return nil, obj.makeErr(err) + } + + return offer, nil + +} + +func (obj *sqlite3Impl) All_Offer(ctx context.Context) ( + rows []*Offer, err error) { + + var __embed_stmt = __sqlbundle_Literal("SELECT offers.id, offers.name, offers.description, offers.type, offers.credit_in_cents, offers.award_credit_duration_days, offers.invitee_credit_duration_days, offers.redeemable_cap, offers.num_redeemed, offers.expires_at, offers.created_at, offers.status FROM offers") + + var __values []interface{} + __values = append(__values) + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __values...) + + __rows, err := obj.driver.Query(__stmt, __values...) + if err != nil { + return nil, obj.makeErr(err) + } + defer __rows.Close() + + for __rows.Next() { + offer := &Offer{} + err = __rows.Scan(&offer.Id, &offer.Name, &offer.Description, &offer.Type, &offer.CreditInCents, &offer.AwardCreditDurationDays, &offer.InviteeCreditDurationDays, &offer.RedeemableCap, &offer.NumRedeemed, &offer.ExpiresAt, &offer.CreatedAt, &offer.Status) + if err != nil { + return nil, obj.makeErr(err) + } + rows = append(rows, offer) + } + if err := __rows.Err(); err != nil { + return nil, obj.makeErr(err) + } + return rows, nil + +} + func (obj *sqlite3Impl) Update_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field, update PendingAudits_Update_Fields) ( @@ -8763,6 +9458,101 @@ func (obj *sqlite3Impl) Update_RegistrationToken_By_Secret(ctx context.Context, return registration_token, nil } +func (obj *sqlite3Impl) Update_Offer_By_Id_And_Status_Equal_Number_And_ExpiresAt_GreaterOrEqual_CreatedAt(ctx context.Context, + offer_id Offer_Id_Field, + update Offer_Update_Fields) ( + offer *Offer, err error) { + var __sets = &__sqlbundle_Hole{} + + var __embed_stmt = __sqlbundle_Literals{Join: "", SQLs: []__sqlbundle_SQL{__sqlbundle_Literal("UPDATE offers SET "), __sets, __sqlbundle_Literal(" WHERE offers.id = ? AND offers.status = 0 AND offers.expires_at >= offers.created_at")}} + + __sets_sql := __sqlbundle_Literals{Join: ", "} + var __values []interface{} + var __args []interface{} + + if update.Name._set { + __values = append(__values, update.Name.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("name = ?")) + } + + if update.Description._set { + __values = append(__values, update.Description.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("description = ?")) + } + + if update.Type._set { + __values = append(__values, update.Type.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("type = ?")) + } + + if update.CreditInCents._set { + __values = append(__values, update.CreditInCents.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("credit_in_cents = ?")) + } + + if update.AwardCreditDurationDays._set { + __values = append(__values, update.AwardCreditDurationDays.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("award_credit_duration_days = ?")) + } + + if update.InviteeCreditDurationDays._set { + __values = append(__values, update.InviteeCreditDurationDays.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("invitee_credit_duration_days = ?")) + } + + if update.RedeemableCap._set { + __values = append(__values, update.RedeemableCap.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("redeemable_cap = ?")) + } + + if update.NumRedeemed._set { + __values = append(__values, update.NumRedeemed.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("num_redeemed = ?")) + } + + if update.ExpiresAt._set { + __values = append(__values, update.ExpiresAt.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("expires_at = ?")) + } + + if update.Status._set { + __values = append(__values, update.Status.value()) + __sets_sql.SQLs = append(__sets_sql.SQLs, __sqlbundle_Literal("status = ?")) + } + + if len(__sets_sql.SQLs) == 0 { + return nil, emptyUpdate() + } + + __args = append(__args, offer_id.value()) + + __values = append(__values, __args...) + __sets.SQL = __sets_sql + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __values...) + + offer = &Offer{} + _, err = obj.driver.Exec(__stmt, __values...) + if err != nil { + return nil, obj.makeErr(err) + } + + var __embed_stmt_get = __sqlbundle_Literal("SELECT offers.id, offers.name, offers.description, offers.type, offers.credit_in_cents, offers.award_credit_duration_days, offers.invitee_credit_duration_days, offers.redeemable_cap, offers.num_redeemed, offers.expires_at, offers.created_at, offers.status FROM offers WHERE offers.id = ? AND offers.status = 0 AND offers.expires_at >= offers.created_at") + + var __stmt_get = __sqlbundle_Render(obj.dialect, __embed_stmt_get) + obj.logStmt("(IMPLIED) "+__stmt_get, __args...) + + err = obj.driver.QueryRow(__stmt_get, __args...).Scan(&offer.Id, &offer.Name, &offer.Description, &offer.Type, &offer.CreditInCents, &offer.AwardCreditDurationDays, &offer.InviteeCreditDurationDays, &offer.RedeemableCap, &offer.NumRedeemed, &offer.ExpiresAt, &offer.CreatedAt, &offer.Status) + if err == sql.ErrNoRows { + return nil, nil + } + if err != nil { + return nil, obj.makeErr(err) + } + return offer, nil +} + func (obj *sqlite3Impl) Delete_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field) ( deleted bool, err error) { @@ -9102,6 +9892,32 @@ func (obj *sqlite3Impl) Delete_ResetPasswordToken_By_Secret(ctx context.Context, } +func (obj *sqlite3Impl) Delete_Offer_By_Id(ctx context.Context, + offer_id Offer_Id_Field) ( + deleted bool, err error) { + + var __embed_stmt = __sqlbundle_Literal("DELETE FROM offers WHERE offers.id = ?") + + var __values []interface{} + __values = append(__values, offer_id.value()) + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, __values...) + + __res, err := obj.driver.Exec(__stmt, __values...) + if err != nil { + return false, obj.makeErr(err) + } + + __count, err := __res.RowsAffected() + if err != nil { + return false, obj.makeErr(err) + } + + return __count > 0, nil + +} + func (obj *sqlite3Impl) getLastPendingAudits(ctx context.Context, pk int64) ( pending_audits *PendingAudits, err error) { @@ -9408,6 +10224,24 @@ func (obj *sqlite3Impl) getLastResetPasswordToken(ctx context.Context, } +func (obj *sqlite3Impl) getLastOffer(ctx context.Context, + pk int64) ( + offer *Offer, err error) { + + var __embed_stmt = __sqlbundle_Literal("SELECT offers.id, offers.name, offers.description, offers.type, offers.credit_in_cents, offers.award_credit_duration_days, offers.invitee_credit_duration_days, offers.redeemable_cap, offers.num_redeemed, offers.expires_at, offers.created_at, offers.status FROM offers WHERE _rowid_ = ?") + + var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt) + obj.logStmt(__stmt, pk) + + offer = &Offer{} + err = obj.driver.QueryRow(__stmt, pk).Scan(&offer.Id, &offer.Name, &offer.Description, &offer.Type, &offer.CreditInCents, &offer.AwardCreditDurationDays, &offer.InviteeCreditDurationDays, &offer.RedeemableCap, &offer.NumRedeemed, &offer.ExpiresAt, &offer.CreatedAt, &offer.Status) + if err != nil { + return nil, obj.makeErr(err) + } + return offer, nil + +} + func (impl sqlite3Impl) isConstraintError(err error) ( constraint string, ok bool) { if e, ok := err.(sqlite3.Error); ok { @@ -9531,6 +10365,16 @@ func (obj *sqlite3Impl) deleteAll(ctx context.Context) (count int64, err error) return 0, obj.makeErr(err) } + __count, err = __res.RowsAffected() + if err != nil { + return 0, obj.makeErr(err) + } + count += __count + __res, err = obj.driver.Exec("DELETE FROM offers;") + if err != nil { + return 0, obj.makeErr(err) + } + __count, err = __res.RowsAffected() if err != nil { return 0, obj.makeErr(err) @@ -9725,6 +10569,15 @@ func (rx *Rx) All_Node_Id(ctx context.Context) ( return tx.All_Node_Id(ctx) } +func (rx *Rx) All_Offer(ctx context.Context) ( + rows []*Offer, err error) { + var tx *Tx + if tx, err = rx.getTx(ctx); err != nil { + return + } + return tx.All_Offer(ctx) +} + func (rx *Rx) All_Project(ctx context.Context) ( rows []*Project, err error) { var tx *Tx @@ -9930,6 +10783,23 @@ func (rx *Rx) Create_Node(ctx context.Context, } +func (rx *Rx) Create_Offer(ctx context.Context, + offer_name Offer_Name_Field, + offer_description Offer_Description_Field, + offer_type Offer_Type_Field, + offer_credit_in_cents Offer_CreditInCents_Field, + offer_award_credit_duration_days Offer_AwardCreditDurationDays_Field, + offer_invitee_credit_duration_days Offer_InviteeCreditDurationDays_Field, + offer_redeemable_cap Offer_RedeemableCap_Field) ( + offer *Offer, err error) { + var tx *Tx + if tx, err = rx.getTx(ctx); err != nil { + return + } + return tx.Create_Offer(ctx, offer_name, offer_description, offer_type, offer_credit_in_cents, offer_award_credit_duration_days, offer_invitee_credit_duration_days, offer_redeemable_cap) + +} + func (rx *Rx) Create_PendingAudits(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field, pending_audits_piece_id PendingAudits_PieceId_Field, @@ -10109,6 +10979,16 @@ func (rx *Rx) Delete_Node_By_Id(ctx context.Context, return tx.Delete_Node_By_Id(ctx, node_id) } +func (rx *Rx) Delete_Offer_By_Id(ctx context.Context, + offer_id Offer_Id_Field) ( + deleted bool, err error) { + var tx *Tx + if tx, err = rx.getTx(ctx); err != nil { + return + } + return tx.Delete_Offer_By_Id(ctx, offer_id) +} + func (rx *Rx) Delete_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field) ( deleted bool, err error) { @@ -10306,6 +11186,28 @@ func (rx *Rx) Get_Node_By_Id(ctx context.Context, return tx.Get_Node_By_Id(ctx, node_id) } +func (rx *Rx) Get_Offer_By_Id(ctx context.Context, + offer_id Offer_Id_Field) ( + offer *Offer, err error) { + var tx *Tx + if tx, err = rx.getTx(ctx); err != nil { + return + } + return tx.Get_Offer_By_Id(ctx, offer_id) +} + +func (rx *Rx) Get_Offer_By_Status_And_Type_And_ExpiresAt_GreaterOrEqual(ctx context.Context, + offer_status Offer_Status_Field, + offer_type Offer_Type_Field, + offer_expires_at_greater_or_equal Offer_ExpiresAt_Field) ( + offer *Offer, err error) { + var tx *Tx + if tx, err = rx.getTx(ctx); err != nil { + return + } + return tx.Get_Offer_By_Status_And_Type_And_ExpiresAt_GreaterOrEqual(ctx, offer_status, offer_type, offer_expires_at_greater_or_equal) +} + func (rx *Rx) Get_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field) ( pending_audits *PendingAudits, err error) { @@ -10509,6 +11411,17 @@ func (rx *Rx) Update_Node_By_Id(ctx context.Context, return tx.Update_Node_By_Id(ctx, node_id, update) } +func (rx *Rx) Update_Offer_By_Id_And_Status_Equal_Number_And_ExpiresAt_GreaterOrEqual_CreatedAt(ctx context.Context, + offer_id Offer_Id_Field, + update Offer_Update_Fields) ( + offer *Offer, err error) { + var tx *Tx + if tx, err = rx.getTx(ctx); err != nil { + return + } + return tx.Update_Offer_By_Id_And_Status_Equal_Number_And_ExpiresAt_GreaterOrEqual_CreatedAt(ctx, offer_id, update) +} + func (rx *Rx) Update_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field, update PendingAudits_Update_Fields) ( @@ -10572,6 +11485,9 @@ type Methods interface { All_Node_Id(ctx context.Context) ( rows []*Id_Row, err error) + All_Offer(ctx context.Context) ( + rows []*Offer, err error) + All_Project(ctx context.Context) ( rows []*Project, err error) @@ -10685,6 +11601,16 @@ type Methods interface { node_contained Node_Contained_Field) ( node *Node, err error) + Create_Offer(ctx context.Context, + offer_name Offer_Name_Field, + offer_description Offer_Description_Field, + offer_type Offer_Type_Field, + offer_credit_in_cents Offer_CreditInCents_Field, + offer_award_credit_duration_days Offer_AwardCreditDurationDays_Field, + offer_invitee_credit_duration_days Offer_InviteeCreditDurationDays_Field, + offer_redeemable_cap Offer_RedeemableCap_Field) ( + offer *Offer, err error) + Create_PendingAudits(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field, pending_audits_piece_id PendingAudits_PieceId_Field, @@ -10765,6 +11691,10 @@ type Methods interface { node_id Node_Id_Field) ( deleted bool, err error) + Delete_Offer_By_Id(ctx context.Context, + offer_id Offer_Id_Field) ( + deleted bool, err error) + Delete_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field) ( deleted bool, err error) @@ -10847,6 +11777,16 @@ type Methods interface { node_id Node_Id_Field) ( node *Node, err error) + Get_Offer_By_Id(ctx context.Context, + offer_id Offer_Id_Field) ( + offer *Offer, err error) + + Get_Offer_By_Status_And_Type_And_ExpiresAt_GreaterOrEqual(ctx context.Context, + offer_status Offer_Status_Field, + offer_type Offer_Type_Field, + offer_expires_at_greater_or_equal Offer_ExpiresAt_Field) ( + offer *Offer, err error) + Get_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field) ( pending_audits *PendingAudits, err error) @@ -10936,6 +11876,11 @@ type Methods interface { update Node_Update_Fields) ( node *Node, err error) + Update_Offer_By_Id_And_Status_Equal_Number_And_ExpiresAt_GreaterOrEqual_CreatedAt(ctx context.Context, + offer_id Offer_Id_Field, + update Offer_Update_Fields) ( + offer *Offer, err error) + Update_PendingAudits_By_NodeId(ctx context.Context, pending_audits_node_id PendingAudits_NodeId_Field, update PendingAudits_Update_Fields) ( diff --git a/satellite/satellitedb/dbx/satellitedb.dbx.postgres.sql b/satellite/satellitedb/dbx/satellitedb.dbx.postgres.sql index dc3c6cec4..ea3153df8 100644 --- a/satellite/satellitedb/dbx/satellitedb.dbx.postgres.sql +++ b/satellite/satellitedb/dbx/satellitedb.dbx.postgres.sql @@ -115,6 +115,21 @@ CREATE TABLE nodes ( contained boolean NOT NULL, PRIMARY KEY ( id ) ); +CREATE TABLE offers ( + id serial NOT NULL, + name text NOT NULL, + description text NOT NULL, + type integer NOT NULL, + credit_in_cents integer NOT NULL, + award_credit_duration_days integer NOT NULL, + invitee_credit_duration_days integer NOT NULL, + redeemable_cap integer NOT NULL, + num_redeemed integer NOT NULL, + expires_at timestamp with time zone, + created_at timestamp with time zone NOT NULL, + status integer NOT NULL, + PRIMARY KEY ( id ) +); CREATE TABLE pending_audits ( node_id bytea NOT NULL, piece_id bytea NOT NULL, diff --git a/satellite/satellitedb/dbx/satellitedb.dbx.sqlite3.sql b/satellite/satellitedb/dbx/satellitedb.dbx.sqlite3.sql index 805e401c6..99e4ed477 100644 --- a/satellite/satellitedb/dbx/satellitedb.dbx.sqlite3.sql +++ b/satellite/satellitedb/dbx/satellitedb.dbx.sqlite3.sql @@ -115,6 +115,21 @@ CREATE TABLE nodes ( contained INTEGER NOT NULL, PRIMARY KEY ( id ) ); +CREATE TABLE offers ( + id INTEGER NOT NULL, + name TEXT NOT NULL, + description TEXT NOT NULL, + type INTEGER NOT NULL, + credit_in_cents INTEGER NOT NULL, + award_credit_duration_days INTEGER NOT NULL, + invitee_credit_duration_days INTEGER NOT NULL, + redeemable_cap INTEGER NOT NULL, + num_redeemed INTEGER NOT NULL, + expires_at TIMESTAMP, + created_at TIMESTAMP NOT NULL, + status INTEGER NOT NULL, + PRIMARY KEY ( id ) +); CREATE TABLE pending_audits ( node_id BLOB NOT NULL, piece_id BLOB NOT NULL, diff --git a/satellite/satellitedb/migrate.go b/satellite/satellitedb/migrate.go index 6a891dcc5..e10afde1b 100644 --- a/satellite/satellitedb/migrate.go +++ b/satellite/satellitedb/migrate.go @@ -673,6 +673,27 @@ func (db *DB) PostgresMigration() *migrate.Migration { CREATE INDEX IF NOT EXISTS node_last_ip ON nodes (last_ip)`, }, }, + { + Description: "Create new tables for free credits program", + Version: 22, + Action: migrate.SQL{` + CREATE TABLE offers ( + id serial NOT NULL, + name text NOT NULL, + description text NOT NULL, + type integer NOT NULL, + credit_in_cents integer NOT NULL, + award_credit_duration_days integer NOT NULL, + invitee_credit_duration_days integer NOT NULL, + redeemable_cap integer NOT NULL, + num_redeemed integer NOT NULL, + expires_at timestamp with time zone, + created_at timestamp with time zone NOT NULL, + status integer NOT NULL, + PRIMARY KEY ( id ) + );`, + }, + }, }, } } diff --git a/satellite/satellitedb/testdata/postgres.v22.sql b/satellite/satellitedb/testdata/postgres.v22.sql new file mode 100644 index 000000000..59d8b13a5 --- /dev/null +++ b/satellite/satellitedb/testdata/postgres.v22.sql @@ -0,0 +1,273 @@ +-- Copied from the corresponding version of dbx generated schema +CREATE TABLE accounting_rollups ( + id bigserial NOT NULL, + node_id bytea NOT NULL, + start_time timestamp with time zone NOT NULL, + put_total bigint NOT NULL, + get_total bigint NOT NULL, + get_audit_total bigint NOT NULL, + get_repair_total bigint NOT NULL, + put_repair_total bigint NOT NULL, + at_rest_total double precision NOT NULL, + PRIMARY KEY ( id ) +); +CREATE TABLE accounting_timestamps ( + name text NOT NULL, + value timestamp with time zone NOT NULL, + PRIMARY KEY ( name ) +); +CREATE TABLE bucket_bandwidth_rollups ( + bucket_name bytea NOT NULL, + project_id bytea NOT NULL, + interval_start timestamp NOT NULL, + interval_seconds integer NOT NULL, + action integer NOT NULL, + inline bigint NOT NULL, + allocated bigint NOT NULL, + settled bigint NOT NULL, + PRIMARY KEY ( bucket_name, project_id, interval_start, action ) +); +CREATE TABLE bucket_storage_tallies ( + bucket_name bytea NOT NULL, + project_id bytea NOT NULL, + interval_start timestamp NOT NULL, + inline bigint NOT NULL, + remote bigint NOT NULL, + remote_segments_count integer NOT NULL, + inline_segments_count integer NOT NULL, + object_count integer NOT NULL, + metadata_size bigint NOT NULL, + PRIMARY KEY ( bucket_name, project_id, interval_start ) +); +CREATE TABLE bucket_usages ( + id bytea NOT NULL, + bucket_id bytea NOT NULL, + rollup_end_time timestamp with time zone NOT NULL, + remote_stored_data bigint NOT NULL, + inline_stored_data bigint NOT NULL, + remote_segments integer NOT NULL, + inline_segments integer NOT NULL, + objects integer NOT NULL, + metadata_size bigint NOT NULL, + repair_egress bigint NOT NULL, + get_egress bigint NOT NULL, + audit_egress bigint NOT NULL, + PRIMARY KEY ( id ) +); +CREATE TABLE bwagreements ( + serialnum text NOT NULL, + storage_node_id bytea NOT NULL, + uplink_id bytea NOT NULL, + action bigint NOT NULL, + total bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + expires_at timestamp with time zone NOT NULL, + PRIMARY KEY ( serialnum ) +); +CREATE TABLE certRecords ( + publickey bytea NOT NULL, + id bytea NOT NULL, + update_at timestamp with time zone NOT NULL, + PRIMARY KEY ( id ) +); +CREATE TABLE injuredsegments ( + path text NOT NULL, + data bytea NOT NULL, + attempted timestamp, + PRIMARY KEY ( path ) +); +CREATE TABLE irreparabledbs ( + segmentpath bytea NOT NULL, + segmentdetail bytea NOT NULL, + pieces_lost_count bigint NOT NULL, + seg_damaged_unix_sec bigint NOT NULL, + repair_attempt_count bigint NOT NULL, + PRIMARY KEY ( segmentpath ) +); +CREATE TABLE nodes ( + id bytea NOT NULL, + address text NOT NULL, + last_ip text NOT NULL, + protocol integer NOT NULL, + type integer NOT NULL, + email text NOT NULL, + wallet text NOT NULL, + free_bandwidth bigint NOT NULL, + free_disk bigint NOT NULL, + major bigint NOT NULL, + minor bigint NOT NULL, + patch bigint NOT NULL, + hash text NOT NULL, + timestamp timestamp with time zone NOT NULL, + release boolean NOT NULL, + latency_90 bigint NOT NULL, + audit_success_count bigint NOT NULL, + total_audit_count bigint NOT NULL, + audit_success_ratio double precision NOT NULL, + uptime_success_count bigint NOT NULL, + total_uptime_count bigint NOT NULL, + uptime_ratio double precision NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + last_contact_success timestamp with time zone NOT NULL, + last_contact_failure timestamp with time zone NOT NULL, + contained boolean NOT NULL, + PRIMARY KEY ( id ) +); +CREATE TABLE offers ( + id serial NOT NULL, + name text NOT NULL, + description text NOT NULL, + type integer NOT NULL, + credit_in_cents integer NOT NULL, + award_credit_duration_days integer NOT NULL, + invitee_credit_duration_days integer NOT NULL, + redeemable_cap integer NOT NULL, + num_redeemed integer NOT NULL, + expires_at timestamp with time zone, + created_at timestamp with time zone NOT NULL, + status integer NOT NULL, + PRIMARY KEY ( id ) +); +CREATE TABLE pending_audits ( + node_id bytea NOT NULL, + piece_id bytea NOT NULL, + stripe_index bigint NOT NULL, + share_size bigint NOT NULL, + expected_share_hash bytea NOT NULL, + reverify_count bigint NOT NULL, + PRIMARY KEY ( node_id ) +); +CREATE TABLE projects ( + id bytea NOT NULL, + name text NOT NULL, + description text NOT NULL, + created_at timestamp with time zone NOT NULL, + PRIMARY KEY ( id ) +); +CREATE TABLE registration_tokens ( + secret bytea NOT NULL, + owner_id bytea, + project_limit integer NOT NULL, + created_at timestamp with time zone NOT NULL, + PRIMARY KEY ( secret ), + UNIQUE ( owner_id ) +); +CREATE TABLE reset_password_tokens ( + secret bytea NOT NULL, + owner_id bytea NOT NULL, + created_at timestamp with time zone NOT NULL, + PRIMARY KEY ( secret ), + UNIQUE ( owner_id ) +); +CREATE TABLE serial_numbers ( + id serial NOT NULL, + serial_number bytea NOT NULL, + bucket_id bytea NOT NULL, + expires_at timestamp NOT NULL, + PRIMARY KEY ( id ) +); +CREATE TABLE storagenode_bandwidth_rollups ( + storagenode_id bytea NOT NULL, + interval_start timestamp NOT NULL, + interval_seconds integer NOT NULL, + action integer NOT NULL, + allocated bigint NOT NULL, + settled bigint NOT NULL, + PRIMARY KEY ( storagenode_id, interval_start, action ) +); +CREATE TABLE storagenode_storage_tallies ( + id bigserial NOT NULL, + node_id bytea NOT NULL, + interval_end_time timestamp with time zone NOT NULL, + data_total double precision NOT NULL, + PRIMARY KEY ( id ) +); +CREATE TABLE users ( + id bytea NOT NULL, + full_name text NOT NULL, + short_name text, + email text NOT NULL, + password_hash bytea NOT NULL, + status integer NOT NULL, + created_at timestamp with time zone NOT NULL, + PRIMARY KEY ( id ) +); +CREATE TABLE api_keys ( + id bytea NOT NULL, + project_id bytea NOT NULL REFERENCES projects( id ) ON DELETE CASCADE, + key bytea NOT NULL, + name text NOT NULL, + created_at timestamp with time zone NOT NULL, + PRIMARY KEY ( id ), + UNIQUE ( key ), + UNIQUE ( name, project_id ) +); +CREATE TABLE project_members ( + member_id bytea NOT NULL REFERENCES users( id ) ON DELETE CASCADE, + project_id bytea NOT NULL REFERENCES projects( id ) ON DELETE CASCADE, + created_at timestamp with time zone NOT NULL, + PRIMARY KEY ( member_id, project_id ) +); +CREATE TABLE used_serials ( + serial_number_id integer NOT NULL REFERENCES serial_numbers( id ) ON DELETE CASCADE, + storage_node_id bytea NOT NULL, + PRIMARY KEY ( serial_number_id, storage_node_id ) +); +CREATE INDEX bucket_name_project_id_interval_start_interval_seconds ON bucket_bandwidth_rollups ( bucket_name, project_id, interval_start, interval_seconds ); +CREATE UNIQUE INDEX bucket_id_rollup ON bucket_usages ( bucket_id, rollup_end_time ); +CREATE INDEX node_last_ip ON nodes ( last_ip ); +CREATE UNIQUE INDEX serial_number ON serial_numbers ( serial_number ); +CREATE INDEX serial_numbers_expires_at_index ON serial_numbers ( expires_at ); +CREATE INDEX storagenode_id_interval_start_interval_seconds ON storagenode_bandwidth_rollups ( storagenode_id, interval_start, interval_seconds ); + +--- + +INSERT INTO "accounting_rollups"("id", "node_id", "start_time", "put_total", "get_total", "get_audit_total", "get_repair_total", "put_repair_total", "at_rest_total") VALUES (1, E'\\367M\\177\\251]t/\\022\\256\\214\\265\\025\\224\\204:\\217\\212\\0102<\\321\\374\\020&\\271Qc\\325\\261\\354\\246\\233'::bytea, '2019-02-09 00:00:00+00', 1000, 2000, 3000, 4000, 0, 5000); + +INSERT INTO "accounting_timestamps" VALUES ('LastAtRestTally', '0001-01-01 00:00:00+00'); +INSERT INTO "accounting_timestamps" VALUES ('LastRollup', '0001-01-01 00:00:00+00'); +INSERT INTO "accounting_timestamps" VALUES ('LastBandwidthTally', '0001-01-01 00:00:00+00'); + +INSERT INTO "nodes"("id", "address", "last_ip", "protocol", "type", "email", "wallet", "free_bandwidth", "free_disk", "major", "minor", "patch", "hash", "timestamp", "release","latency_90", "audit_success_count", "total_audit_count", "audit_success_ratio", "uptime_success_count", "total_uptime_count", "uptime_ratio", "created_at", "updated_at", "last_contact_success", "last_contact_failure", "contained") VALUES (E'\\153\\313\\233\\074\\327\\177\\136\\070\\346\\001', '127.0.0.1:55516', '', 0, 4, '', '', -1, -1, 0, 1, 0, '', 'epoch', false, 0, 0, 5, 0, 0, 5, 0, '2019-02-14 08:07:31.028103+00', '2019-02-14 08:07:31.108963+00', 'epoch', 'epoch', false); +INSERT INTO "nodes"("id", "address", "last_ip", "protocol", "type", "email", "wallet", "free_bandwidth", "free_disk", "major", "minor", "patch", "hash", "timestamp", "release","latency_90", "audit_success_count", "total_audit_count", "audit_success_ratio", "uptime_success_count", "total_uptime_count", "uptime_ratio", "created_at", "updated_at", "last_contact_success", "last_contact_failure", "contained") VALUES (E'\\006\\223\\250R\\221\\005\\365\\377v>0\\266\\365\\216\\255?\\347\\244\\371?2\\264\\262\\230\\007<\\001\\262\\263\\237\\247n', '127.0.0.1:55518', '', 0, 4, '', '', -1, -1, 0, 1, 0, '', 'epoch', false, 0, 0, 0, 1, 3, 3, 1, '2019-02-14 08:07:31.028103+00', '2019-02-14 08:07:31.108963+00', 'epoch', 'epoch', false); +INSERT INTO "nodes"("id", "address", "last_ip", "protocol", "type", "email", "wallet", "free_bandwidth", "free_disk", "major", "minor", "patch", "hash", "timestamp", "release","latency_90", "audit_success_count", "total_audit_count", "audit_success_ratio", "uptime_success_count", "total_uptime_count", "uptime_ratio", "created_at", "updated_at", "last_contact_success", "last_contact_failure", "contained") VALUES (E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014', '127.0.0.1:55517', '', 0, 4, '', '', -1, -1, 0, 1, 0, '', 'epoch', false, 0, 0, 0, 1, 0, 0, 1, '2019-02-14 08:07:31.028103+00', '2019-02-14 08:07:31.108963+00', 'epoch', 'epoch', false); + + +INSERT INTO "projects"("id", "name", "description", "created_at") VALUES (E'\\022\\217/\\014\\376!K\\023\\276\\031\\311}m\\236\\205\\300'::bytea, 'ProjectName', 'projects description', '2019-02-14 08:28:24.254934+00'); +INSERT INTO "api_keys"("id", "project_id", "key", "name", "created_at") VALUES (E'\\334/\\302;\\225\\355O\\323\\276f\\247\\354/6\\241\\033'::bytea, E'\\022\\217/\\014\\376!K\\023\\276\\031\\311}m\\236\\205\\300'::bytea, E'\\000]\\326N \\343\\270L\\327\\027\\337\\242\\240\\322mOl\\0318\\251.P I'::bytea, 'key 2', '2019-02-14 08:28:24.267934+00'); + +INSERT INTO "users"("id", "full_name", "short_name", "email", "password_hash", "status", "created_at") VALUES (E'\\363\\311\\033w\\222\\303Ci\\265\\343U\\303\\312\\204",'::bytea, 'Noahson', 'William', '1email1@ukr.net', E'some_readable_hash'::bytea, 1, '2019-02-14 08:28:24.614594+00'); +INSERT INTO "projects"("id", "name", "description", "created_at") VALUES (E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014'::bytea, 'projName1', 'Test project 1', '2019-02-14 08:28:24.636949+00'); +INSERT INTO "project_members"("member_id", "project_id", "created_at") VALUES (E'\\363\\311\\033w\\222\\303Ci\\265\\343U\\303\\312\\204",'::bytea, E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014'::bytea, '2019-02-14 08:28:24.677953+00'); + +INSERT INTO "bwagreements"("serialnum", "storage_node_id", "action", "total", "created_at", "expires_at", "uplink_id") VALUES ('8fc0ceaa-984c-4d52-bcf4-b5429e1e35e812FpiifDbcJkePa12jxjDEutKrfLmwzT7sz2jfVwpYqgtM8B74c', E'\\245Z[/\\333\\022\\011\\001\\036\\003\\204\\005\\032.\\206\\333E\\261\\342\\227=y,}aRaH6\\240\\370\\000'::bytea, 1, 666, '2019-02-14 15:09:54.420181+00', '2019-02-14 16:09:54+00', E'\\253Z+\\374eFm\\245$\\036\\206\\335\\247\\263\\350x\\\\\\304+\\364\\343\\364+\\276fIJQ\\361\\014\\232\\000'::bytea); +INSERT INTO "irreparabledbs" ("segmentpath", "segmentdetail", "pieces_lost_count", "seg_damaged_unix_sec", "repair_attempt_count") VALUES ('\x49616d5365676d656e746b6579696e666f30', '\x49616d5365676d656e7464657461696c696e666f30', 10, 1550159554, 10); + +INSERT INTO "injuredsegments" ("path", "data") VALUES ('0', '\x0a0130120100'); +INSERT INTO "injuredsegments" ("path", "data") VALUES ('here''s/a/great/path', '\x0a136865726527732f612f67726561742f70617468120a0102030405060708090a'); +INSERT INTO "injuredsegments" ("path", "data") VALUES ('yet/another/cool/path', '\x0a157965742f616e6f746865722f636f6f6c2f70617468120a0102030405060708090a'); +INSERT INTO "injuredsegments" ("path", "data") VALUES ('so/many/iconic/paths/to/choose/from', '\x0a23736f2f6d616e792f69636f6e69632f70617468732f746f2f63686f6f73652f66726f6d120a0102030405060708090a'); + +INSERT INTO "certrecords" VALUES (E'0Y0\\023\\006\\007*\\206H\\316=\\002\\001\\006\\010*\\206H\\316=\\003\\001\\007\\003B\\000\\004\\360\\267\\227\\377\\253u\\222\\337Y\\324C:GQ\\010\\277v\\010\\315D\\271\\333\\337.\\203\\023=C\\343\\014T%6\\027\\362?\\214\\326\\017U\\334\\000\\260\\224\\260J\\221\\304\\331F\\304\\221\\236zF,\\325\\326l\\215\\306\\365\\200\\022', E'L\\301|\\200\\247}F|1\\320\\232\\037n\\335\\241\\206\\244\\242\\207\\204.\\253\\357\\326\\352\\033Dt\\202`\\022\\325', '2019-02-14 08:07:31.335028+00'); + +INSERT INTO "bucket_usages" ("id", "bucket_id", "rollup_end_time", "remote_stored_data", "inline_stored_data", "remote_segments", "inline_segments", "objects", "metadata_size", "repair_egress", "get_egress", "audit_egress") VALUES (E'\\153\\313\\233\\074\\327\\177\\136\\070\\346\\001",'::bytea, E'\\366\\146\\032\\321\\316\\161\\070\\133\\302\\271",'::bytea, '2019-03-06 08:28:24.677953+00', 10, 11, 12, 13, 14, 15, 16, 17, 18); + +INSERT INTO "registration_tokens" ("secret", "owner_id", "project_limit", "created_at") VALUES (E'\\070\\127\\144\\013\\332\\344\\102\\376\\306\\056\\303\\130\\106\\132\\321\\276\\321\\274\\170\\264\\054\\333\\221\\116\\154\\221\\335\\070\\220\\146\\344\\216'::bytea, null, 1, '2019-02-14 08:28:24.677953+00'); + +INSERT INTO "serial_numbers" ("id", "serial_number", "bucket_id", "expires_at") VALUES (1, E'0123456701234567'::bytea, E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014/testbucket'::bytea, '2019-03-06 08:28:24.677953+00'); +INSERT INTO "used_serials" ("serial_number_id", "storage_node_id") VALUES (1, E'\\006\\223\\250R\\221\\005\\365\\377v>0\\266\\365\\216\\255?\\347\\244\\371?2\\264\\262\\230\\007<\\001\\262\\263\\237\\247n'); + +INSERT INTO "storagenode_bandwidth_rollups" ("storagenode_id", "interval_start", "interval_seconds", "action", "allocated", "settled") VALUES (E'\\006\\223\\250R\\221\\005\\365\\377v>0\\266\\365\\216\\255?\\347\\244\\371?2\\264\\262\\230\\007<\\001\\262\\263\\237\\247n', '2019-03-06 08:00:00.000000+00', 3600, 1, 1024, 2024); +INSERT INTO "storagenode_storage_tallies" VALUES (1, E'\\3510\\323\\225"~\\036<\\342\\330m\\0253Jhr\\246\\233K\\246#\\2303\\351\\256\\275j\\212UM\\362\\207', '2019-02-14 08:16:57.812849+00', 1000); + +INSERT INTO "bucket_bandwidth_rollups" ("bucket_name", "project_id", "interval_start", "interval_seconds", "action", "inline", "allocated", "settled") VALUES (E'testbucket'::bytea, E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014'::bytea,'2019-03-06 08:00:00.000000+00', 3600, 1, 1024, 2024, 3024); +INSERT INTO "bucket_storage_tallies" ("bucket_name", "project_id", "interval_start", "inline", "remote", "remote_segments_count", "inline_segments_count", "object_count", "metadata_size") VALUES (E'testbucket'::bytea, E'\\363\\342\\363\\371>+F\\256\\263\\300\\273|\\342N\\347\\014'::bytea,'2019-03-06 08:00:00.000000+00', 4024, 5024, 0, 0, 0, 0); + +INSERT INTO "reset_password_tokens" ("secret", "owner_id", "created_at") VALUES (E'\\070\\127\\144\\013\\332\\344\\102\\376\\306\\056\\303\\130\\106\\132\\321\\276\\321\\274\\170\\264\\054\\333\\221\\116\\154\\221\\335\\070\\220\\146\\344\\216'::bytea, E'\\363\\311\\033w\\222\\303Ci\\265\\343U\\303\\312\\204",'::bytea, '2019-05-08 08:28:24.677953+00'); + +INSERT INTO "pending_audits" ("node_id", "piece_id", "stripe_index", "share_size", "expected_share_hash", "reverify_count") VALUES (E'\\153\\313\\233\\074\\327\\177\\136\\070\\346\\001'::bytea, E'\\363\\311\\033w\\222\\303Ci\\265\\343U\\303\\312\\204",'::bytea, 5, 1024, E'\\070\\127\\144\\013\\332\\344\\102\\376\\306\\056\\303\\130\\106\\132\\321\\276\\321\\274\\170\\264\\054\\333\\221\\116\\154\\221\\335\\070\\220\\146\\344\\216'::bytea, 1); + +-- NEW DATA -- + +INSERT INTO "offers" ("id", "name", "description", "type", "credit_in_cents", "award_credit_duration_days", "invitee_credit_duration_days", "redeemable_cap", "expires_at", "created_at", "num_redeemed", "status") VALUES (1, 'testOffer', 'Test offer 1', 0, 1000, 14, 14, 50, '2019-03-14 08:28:24.636949+00', '2019-02-14 08:28:24.636949+00', 0, 0); \ No newline at end of file