@@ -26,26 +26,27 @@ import (
2626 "yunion.io/x/pkg/util/billing"
2727 "yunion.io/x/sqlchemy"
2828
29- "yunion.io/x/onecloud/pkg/apis"
3029 api "yunion.io/x/onecloud/pkg/apis/billing"
3130 billing_api "yunion.io/x/onecloud/pkg/apis/billing"
3231 notifyapi "yunion.io/x/onecloud/pkg/apis/notify"
3332 "yunion.io/x/onecloud/pkg/cloudcommon/db"
3433 "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
3534 "yunion.io/x/onecloud/pkg/compute/options"
36- "yunion.io/x/onecloud/pkg/httperrors"
3735 "yunion.io/x/onecloud/pkg/mcclient"
3836 "yunion.io/x/onecloud/pkg/mcclient/auth"
3937 "yunion.io/x/onecloud/pkg/mcclient/modules/notify"
38+ "yunion.io/x/onecloud/pkg/util/logclient"
4039 "yunion.io/x/onecloud/pkg/util/stringutils2"
4140)
4241
4342type SBillingResourceBase struct {
4443 // 计费类型, 按量、包年包月
4544 // example: postpaid
4645 BillingType string `width:"36" charset:"ascii" nullable:"true" default:"postpaid" list:"user" create:"optional" json:"billing_type"`
47- // 过期时间
48- ExpiredAt time.Time `nullable:"true" list:"user" create:"optional" json:"expired_at"`
46+ // 包年包月到期时间
47+ ExpiredAt time.Time `nullable:"true" list:"user" json:"expired_at"`
48+ // 到期释放时间
49+ ReleaseAt time.Time `nullable:"true" list:"user" create:"optional" json:"release_at"`
4950 // 计费周期
5051 BillingCycle string `width:"10" charset:"ascii" nullable:"true" list:"user" create:"optional" json:"billing_cycle"`
5152 // 是否自动续费
@@ -62,10 +63,35 @@ func (self *SBillingResourceBase) GetChargeType() string {
6263 }
6364}
6465
66+ func (self * SBillingResourceBase ) SetReleaseAt (releaseAt time.Time ) {
67+ self .ReleaseAt = releaseAt
68+ }
69+
70+ func (self * SBillingResourceBase ) GetExpiredAt () time.Time {
71+ return self .ExpiredAt
72+ }
73+
74+ func (self * SBillingResourceBase ) SetExpiredAt (expireAt time.Time ) {
75+ self .ExpiredAt = expireAt
76+ }
77+
78+ func (self * SBillingResourceBase ) SetBillingCycle (billingCycle string ) {
79+ self .BillingCycle = billingCycle
80+ }
81+
82+ func (self * SBillingResourceBase ) SetBillingType (billingType string ) {
83+ self .BillingType = billingType
84+ }
85+
86+ func (self * SBillingResourceBase ) GetBillingType () string {
87+ return self .BillingType
88+ }
89+
6590func (self * SBillingResourceBase ) getBillingBaseInfo () SBillingBaseInfo {
6691 info := SBillingBaseInfo {}
6792 info .ChargeType = self .GetChargeType ()
6893 info .ExpiredAt = self .ExpiredAt
94+ info .ReleaseAt = self .ReleaseAt
6995 if self .GetChargeType () == api .BILLING_TYPE_PREPAID {
7096 info .BillingCycle = self .BillingCycle
7197 }
@@ -93,7 +119,7 @@ func (self *SBillingResourceBase) IsValidPrePaid() bool {
93119func (self * SBillingResourceBase ) IsValidPostPaid () bool {
94120 if self .BillingType == api .BILLING_TYPE_POSTPAID {
95121 now := time .Now ().UTC ()
96- if self .ExpiredAt .After (now ) {
122+ if self .ReleaseAt .After (now ) {
97123 return true
98124 }
99125 }
@@ -103,6 +129,7 @@ func (self *SBillingResourceBase) IsValidPostPaid() bool {
103129type SBillingBaseInfo struct {
104130 ChargeType string `json:",omitempty"`
105131 ExpiredAt time.Time `json:",omitempty"`
132+ ReleaseAt time.Time `json:",omitempty"`
106133 BillingCycle string `json:",omitempty"`
107134}
108135
@@ -170,43 +197,14 @@ func (manager *SBillingResourceBaseManager) OrderByExtraFields(
170197func ListExpiredPostpaidResources (
171198 q * sqlchemy.SQuery , limit int ) * sqlchemy.SQuery {
172199 q = q .Equals ("billing_type" , api .BILLING_TYPE_POSTPAID )
173- q = q .IsNotNull ("expired_at " )
174- q = q .LT ("expired_at " , time .Now ())
200+ q = q .IsNotNull ("release_at " )
201+ q = q .LT ("release_at " , time .Now ())
175202 if limit > 0 {
176203 q = q .Limit (limit )
177204 }
178205 return q
179206}
180207
181- func ParseBillingCycleInput (billingBase * SBillingResourceBase , input apis.PostpaidExpireInput ) (* billing.SBillingCycle , error ) {
182- var (
183- bc billing.SBillingCycle
184- err error
185- durationStr string
186- )
187- if len (input .Duration ) == 0 {
188- if input .ExpireTime .IsZero () {
189- return nil , httperrors .NewInputParameterError ("missing duration/expire_time" )
190- }
191- timeC := billingBase .ExpiredAt
192- if timeC .IsZero () {
193- timeC = time .Now ()
194- }
195- dur := input .ExpireTime .Sub (timeC )
196- if dur <= 0 {
197- return nil , httperrors .NewInputParameterError ("expire time is before current expire at" )
198- }
199- bc = billing .DurationToBillingCycle (dur )
200- } else {
201- bc , err = billing .ParseBillingCycle (durationStr )
202- if err != nil {
203- return nil , httperrors .NewInputParameterError ("invalid duration %s: %s" , durationStr , err )
204- }
205- }
206-
207- return & bc , nil
208- }
209-
210208type SBillingResourceCheckManager struct {
211209 db.SResourceBaseManager
212210}
@@ -242,6 +240,55 @@ type IBillingModelManager interface {
242240type IBillingModel interface {
243241 db.IModel
244242 GetExpiredAt () time.Time
243+ SetReleaseAt (releaseAt time.Time )
244+ SetExpiredAt (expireAt time.Time )
245+ SetBillingCycle (billingCycle string )
246+ SetBillingType (billingType string )
247+ GetBillingType () string
248+ }
249+
250+ func SaveReleaseAt (ctx context.Context , model IBillingModel , userCred mcclient.TokenCredential , releaseAt time.Time ) error {
251+ diff , err := db .Update (model , func () error {
252+ model .SetReleaseAt (releaseAt )
253+ return nil
254+ })
255+ if err != nil {
256+ return errors .Wrap (err , "Update" )
257+ }
258+ if len (diff ) > 0 {
259+ db .OpsLog .LogEvent (model , db .ACT_SET_RELEASE_TIME , fmt .Sprintf ("release at: %s" , releaseAt ), userCred )
260+ }
261+ if len (diff ) > 0 && userCred != nil {
262+ logclient .AddActionLogWithContext (ctx , model , logclient .ACT_SET_RELEASE_TIME , diff , userCred , true )
263+ }
264+ return nil
265+ }
266+
267+ func SaveRenewInfo (
268+ ctx context.Context , userCred mcclient.TokenCredential ,
269+ model IBillingModel , bc * billing.SBillingCycle , expireAt * time.Time , billingType string ,
270+ ) error {
271+ _ , err := db .Update (model , func () error {
272+ if billingType == "" {
273+ billingType = billing_api .BILLING_TYPE_PREPAID
274+ }
275+ if model .GetBillingType () == "" {
276+ model .SetBillingType (billingType )
277+ }
278+ if expireAt != nil && ! expireAt .IsZero () {
279+ model .SetExpiredAt (* expireAt )
280+ } else if bc != nil {
281+ model .SetBillingCycle (bc .String ())
282+ model .SetExpiredAt (bc .EndAt (model .GetExpiredAt ()))
283+ }
284+ return nil
285+ })
286+ if err != nil {
287+ log .Errorf ("UpdateItem error %s" , err )
288+ return err
289+ }
290+ db .OpsLog .LogEvent (model , db .ACT_RENEW , model .GetShortDesc (ctx ), userCred )
291+ return nil
245292}
246293
247294func fetchExpiredModels (manager db.IModelManager , advanceDay int ) ([]IBillingModel , error ) {
0 commit comments