[MM-29157] Cloud invoices logic (#16056)
* Cloud invoices logic This commit includes all the code needed to get and print invoices from CWS
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
8f895908fc
Коммит
b68f171162
@@ -4,9 +4,13 @@
|
||||
package api4
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/audit"
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
@@ -30,6 +34,8 @@ func (api *API) InitCloud() {
|
||||
|
||||
// GET /api/v4/cloud/subscription
|
||||
api.BaseRoutes.Cloud.Handle("/subscription", api.ApiSessionRequired(getSubscription)).Methods("GET")
|
||||
api.BaseRoutes.Cloud.Handle("/subscription/invoices", api.ApiSessionRequired(getInvoicesForSubscription)).Methods("GET")
|
||||
api.BaseRoutes.Cloud.Handle("/subscription/invoices/{invoice_id:in_[A-Za-z0-9]+}/pdf", api.ApiSessionRequired(getSubscriptionInvoicePDF)).Methods("GET")
|
||||
}
|
||||
|
||||
func getSubscription(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
@@ -254,3 +260,68 @@ func confirmCustomerPayment(c *Context, w http.ResponseWriter, r *http.Request)
|
||||
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
|
||||
func getInvoicesForSubscription(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud {
|
||||
c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.license_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
|
||||
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
||||
return
|
||||
}
|
||||
|
||||
invoices, appErr := c.App.Cloud().GetInvoicesForSubscription()
|
||||
if appErr != nil {
|
||||
c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.request_error", nil, appErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
json, err := json.Marshal(invoices)
|
||||
if err != nil {
|
||||
c.Err = model.NewAppError("Api4.getInvoicesForSubscription", "api.cloud.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(json)
|
||||
}
|
||||
|
||||
func getSubscriptionInvoicePDF(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
if c.App.Srv().License() == nil || !*c.App.Srv().License().Features.Cloud {
|
||||
c.Err = model.NewAppError("Api4.getSuscriptionInvoicePDF", "api.cloud.license_error", nil, "", http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
c.RequireInvoiceId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
|
||||
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
|
||||
return
|
||||
}
|
||||
|
||||
pdfData, appErr := c.App.Cloud().GetInvoicePDF(c.Params.InvoiceId)
|
||||
if appErr != nil {
|
||||
c.Err = model.NewAppError("Api4.getSuscriptionInvoicePDF", "api.cloud.request_error", nil, appErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
err := writeFileResponse(
|
||||
fmt.Sprintf("%s.pdf", c.Params.InvoiceId),
|
||||
"application/pdf",
|
||||
int64(binary.Size(pdfData)),
|
||||
time.Now(),
|
||||
*c.App.Config().ServiceSettings.WebserverMode,
|
||||
bytes.NewReader(pdfData),
|
||||
false,
|
||||
w,
|
||||
r,
|
||||
)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,4 +18,6 @@ type CloudInterface interface {
|
||||
UpdateCloudCustomerAddress(address *model.Address) (*model.CloudCustomer, *model.AppError)
|
||||
|
||||
GetSubscription() (*model.Subscription, *model.AppError)
|
||||
GetInvoicesForSubscription() ([]*model.Invoice, *model.AppError)
|
||||
GetInvoicePDF(invoiceID string) ([]byte, *model.AppError)
|
||||
}
|
||||
|
||||
@@ -5702,6 +5702,19 @@ func (c *Client4) GetSubscription() (*Subscription, *Response) {
|
||||
return subscription, BuildResponse(r)
|
||||
}
|
||||
|
||||
func (c *Client4) GetInvoicesForSubscription() ([]*Invoice, *Response) {
|
||||
r, appErr := c.DoApiGet(c.GetCloudRoute()+"/subscription/invoices", "")
|
||||
if appErr != nil {
|
||||
return nil, BuildErrorResponse(r, appErr)
|
||||
}
|
||||
defer closeBody(r)
|
||||
|
||||
var invoices []*Invoice
|
||||
json.NewDecoder(r.Body).Decode(&invoices)
|
||||
|
||||
return invoices, BuildResponse(r)
|
||||
}
|
||||
|
||||
func (c *Client4) UpdateCloudCustomer(customerInfo *CloudCustomerInfo) (*CloudCustomer, *Response) {
|
||||
customerBytes, _ := json.Marshal(customerInfo)
|
||||
|
||||
|
||||
@@ -84,3 +84,29 @@ type Subscription struct {
|
||||
DNS string `json:"dns"`
|
||||
IsPaidTier string `json:"is_paid_tier"`
|
||||
}
|
||||
|
||||
// Invoice model represents a cloud invoice
|
||||
type Invoice struct {
|
||||
ID string `json:"id"`
|
||||
Number string `json:"number"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
Total int64 `json:"total"`
|
||||
Tax int64 `json:"tax"`
|
||||
Status string `json:"status"`
|
||||
Description string `json:"description"`
|
||||
PeriodStart int64 `json:"period_start"`
|
||||
PeriodEnd int64 `json:"period_end"`
|
||||
SubscriptionID string `json:"subscription_id"`
|
||||
Items []*InvoiceLineItem `json:"line_items"`
|
||||
}
|
||||
|
||||
// InvoiceLineItem model represents a cloud invoice lineitem tied to an invoice.
|
||||
type InvoiceLineItem struct {
|
||||
PriceID string `json:"price_id"`
|
||||
Total int64 `json:"total"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
PricePerUnit int64 `json:"price_per_unit"`
|
||||
Description string `json:"description"`
|
||||
Type string `json:"type"`
|
||||
Metadata map[string]interface{} `json:"metadata"`
|
||||
}
|
||||
|
||||
@@ -663,3 +663,15 @@ func (c *Context) RequireBotUserId() *Context {
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Context) RequireInvoiceId() *Context {
|
||||
if c.Err != nil {
|
||||
return c
|
||||
}
|
||||
|
||||
if len(c.Params.InvoiceId) != 27 {
|
||||
c.SetInvalidUrlParam("invoice_id")
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -80,6 +80,9 @@ type Params struct {
|
||||
FilterParentTeamPermitted bool
|
||||
CategoryId string
|
||||
WarnMetricId string
|
||||
|
||||
// Cloud
|
||||
InvoiceId string
|
||||
}
|
||||
|
||||
func ParamsFromRequest(r *http.Request) *Params {
|
||||
@@ -216,6 +219,10 @@ func ParamsFromRequest(r *http.Request) *Params {
|
||||
params.RemoteId = val
|
||||
}
|
||||
|
||||
if val, ok := props["invoice_id"]; ok {
|
||||
params.InvoiceId = val
|
||||
}
|
||||
|
||||
params.Scope = query.Get("scope")
|
||||
|
||||
if val, err := strconv.Atoi(query.Get("page")); err != nil || val < 0 {
|
||||
|
||||
Ссылка в новой задаче
Block a user