Compare commits
	
		
			2 Commits
		
	
	
		
			059638f3a7
			...
			63585e31f6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 63585e31f6 | |||
| c697da63b9 | 
| @ -164,6 +164,8 @@ func (app *application) CreateCustomerAndSubscribeToPlan(w http.ResponseWriter, | |||||||
| 			ExpiryMonth:         data.ExpiryMonth, | 			ExpiryMonth:         data.ExpiryMonth, | ||||||
| 			ExpiryYear:          data.ExpiryYear, | 			ExpiryYear:          data.ExpiryYear, | ||||||
| 			TransactionStatusID: 2, | 			TransactionStatusID: 2, | ||||||
|  | 			PaymentIntent:       subscription.ID, | ||||||
|  | 			PaymentMethod:       data.PaymentMethod, | ||||||
| 		} | 		} | ||||||
| 		txnID, err := app.SaveTransaction(txn) | 		txnID, err := app.SaveTransaction(txn) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| @ -514,11 +516,35 @@ func (app *application) ResetPassword(w http.ResponseWriter, r *http.Request) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (app *application) AllSales(w http.ResponseWriter, r *http.Request) { | func (app *application) AllSales(w http.ResponseWriter, r *http.Request) { | ||||||
| 	allSales, err := app.DB.GetAllOrders(false) | 	var payload struct { | ||||||
|  | 		PageSize    int `json:"page_size"` | ||||||
|  | 		CurrentPage int `json:"page"` | ||||||
|  | 	} | ||||||
|  | 	err := app.readJSON(w, r, &payload) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		app.badRequest(w, r, err) | 		app.badRequest(w, r, err) | ||||||
| 	} | 	} | ||||||
| 	app.writeJSON(w, http.StatusOK, allSales) |  | ||||||
|  | 	allSales, lastPage, totalRecords, err := app.DB.GetAllOrdersPaginated(false, 2, 1) | ||||||
|  | 	if err != nil { | ||||||
|  | 		app.badRequest(w, r, err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var resp struct { | ||||||
|  | 		CurrentPage  int             `json:"current_page"` | ||||||
|  | 		PageSize     int             `json:"page_size"` | ||||||
|  | 		LastPage     int             `json:"last_page"` | ||||||
|  | 		TotalRecords int             `json:"total_records"` | ||||||
|  | 		Orders       []*models.Order `json:"orders"` | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	resp.CurrentPage = 1 | ||||||
|  | 	resp.PageSize = payload.PageSize | ||||||
|  | 	resp.LastPage = lastPage | ||||||
|  | 	resp.TotalRecords = totalRecords | ||||||
|  | 	resp.Orders = allSales | ||||||
|  |  | ||||||
|  | 	app.writeJSON(w, http.StatusOK, resp) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (app *application) AllSubscriptions(w http.ResponseWriter, r *http.Request) { | func (app *application) AllSubscriptions(w http.ResponseWriter, r *http.Request) { | ||||||
| @ -587,3 +613,50 @@ func (app *application) RefundCharge(w http.ResponseWriter, r *http.Request) { | |||||||
|  |  | ||||||
| 	app.writeJSON(w, http.StatusOK, resp) | 	app.writeJSON(w, http.StatusOK, resp) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (app *application) CancelSubscription(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 	var subToCancel struct { | ||||||
|  | 		ID            int    `json:"id"` | ||||||
|  | 		PaymentIntent string `json:"pi"` | ||||||
|  | 		Currency      string `json:"currency"` | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err := app.readJSON(w, r, &subToCancel) | ||||||
|  | 	if err != nil { | ||||||
|  | 		app.errorLog.Println(err) | ||||||
|  | 		app.badRequest(w, r, err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// validate | ||||||
|  |  | ||||||
|  | 	card := cards.Card{ | ||||||
|  | 		Secret:   app.config.stripe.secret, | ||||||
|  | 		Key:      app.config.stripe.key, | ||||||
|  | 		Currency: subToCancel.Currency, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = card.CancelSubscription(subToCancel.PaymentIntent) | ||||||
|  | 	if err != nil { | ||||||
|  | 		app.errorLog.Println(err) | ||||||
|  | 		app.badRequest(w, r, err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// update status in DB | ||||||
|  | 	err = app.DB.UpdateOrderStatus(subToCancel.ID, 3) | ||||||
|  | 	if err != nil { | ||||||
|  | 		app.badRequest( | ||||||
|  | 			w, | ||||||
|  | 			r, | ||||||
|  | 			errors.New("the subscription was refunded, but the database could not be updated"), | ||||||
|  | 		) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var resp jsonResponse | ||||||
|  | 	resp.OK = true | ||||||
|  | 	resp.Message = "Subscription canceled" | ||||||
|  |  | ||||||
|  | 	app.writeJSON(w, http.StatusOK, resp) | ||||||
|  | } | ||||||
|  | |||||||
| @ -53,12 +53,9 @@ func (app *application) writeJSON( | |||||||
| } | } | ||||||
|  |  | ||||||
| func (app *application) badRequest(w http.ResponseWriter, r *http.Request, err error) error { | func (app *application) badRequest(w http.ResponseWriter, r *http.Request, err error) error { | ||||||
| 	var payload struct { | 	var payload jsonResponse | ||||||
| 		Error   bool   `json:"error"` |  | ||||||
| 		Message string `json:"message"` |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	payload.Error = true | 	payload.OK = false | ||||||
| 	payload.Message = err.Error() | 	payload.Message = err.Error() | ||||||
|  |  | ||||||
| 	out, err := json.MarshalIndent(payload, "", "\t") | 	out, err := json.MarshalIndent(payload, "", "\t") | ||||||
| @ -73,11 +70,8 @@ func (app *application) badRequest(w http.ResponseWriter, r *http.Request, err e | |||||||
| } | } | ||||||
|  |  | ||||||
| func (app *application) invalidCredentials(w http.ResponseWriter) error { | func (app *application) invalidCredentials(w http.ResponseWriter) error { | ||||||
| 	var payload struct { | 	var payload jsonResponse | ||||||
| 		Error   bool   `json:"error"` | 	payload.OK = false | ||||||
| 		Message string `json:"message"` |  | ||||||
| 	} |  | ||||||
| 	payload.Error = true |  | ||||||
| 	payload.Message = "invalid authentication credentials" | 	payload.Message = "invalid authentication credentials" | ||||||
|  |  | ||||||
| 	err := app.writeJSON(w, http.StatusUnauthorized, payload) | 	err := app.writeJSON(w, http.StatusUnauthorized, payload) | ||||||
|  | |||||||
| @ -36,6 +36,7 @@ func (app *application) routes() http.Handler { | |||||||
| 		mux.Post("/all-subscriptions", app.AllSubscriptions) | 		mux.Post("/all-subscriptions", app.AllSubscriptions) | ||||||
| 		mux.Post("/get-sale/{id}", app.GetSale) | 		mux.Post("/get-sale/{id}", app.GetSale) | ||||||
| 		mux.Post("/refund", app.RefundCharge) | 		mux.Post("/refund", app.RefundCharge) | ||||||
|  | 		mux.Post("/cancel-subscription", app.CancelSubscription) | ||||||
| 	}) | 	}) | ||||||
| 	mux.Post("/api/forgot-password", app.SendPasswordResetEmail) | 	mux.Post("/api/forgot-password", app.SendPasswordResetEmail) | ||||||
| 	mux.Post("/api/reset-password", app.ResetPassword) | 	mux.Post("/api/reset-password", app.ResetPassword) | ||||||
|  | |||||||
| @ -384,9 +384,16 @@ func (app *application) ShowSale(w http.ResponseWriter, r *http.Request) { | |||||||
| 	stringMap := make(map[string]string) | 	stringMap := make(map[string]string) | ||||||
| 	stringMap["title"] = "Sale" | 	stringMap["title"] = "Sale" | ||||||
| 	stringMap["cancel"] = "/admin/all-sales" | 	stringMap["cancel"] = "/admin/all-sales" | ||||||
|  | 	stringMap["refund-url"] = "/api/admin/refund" | ||||||
|  | 	stringMap["refund-btn"] = "Refund Order" | ||||||
|  | 	stringMap["refund-badge"] = "Refunded" | ||||||
|  |  | ||||||
|  | 	intMap := make(map[string]int) | ||||||
|  | 	intMap["isRefund"] = 1 | ||||||
|  |  | ||||||
| 	if err := app.renderTemplate(w, r, "sale", &templateData{ | 	if err := app.renderTemplate(w, r, "sale", &templateData{ | ||||||
| 		StringMap: stringMap, | 		StringMap: stringMap, | ||||||
|  | 		IntMap:    intMap, | ||||||
| 	}); err != nil { | 	}); err != nil { | ||||||
| 		app.errorLog.Println(err) | 		app.errorLog.Println(err) | ||||||
| 	} | 	} | ||||||
| @ -396,9 +403,16 @@ func (app *application) ShowSubscriptions(w http.ResponseWriter, r *http.Request | |||||||
| 	stringMap := make(map[string]string) | 	stringMap := make(map[string]string) | ||||||
| 	stringMap["title"] = "Subscriptions" | 	stringMap["title"] = "Subscriptions" | ||||||
| 	stringMap["cancel"] = "/admin/all-subscriptions" | 	stringMap["cancel"] = "/admin/all-subscriptions" | ||||||
|  | 	stringMap["refund-url"] = "/api/admin/cancel-subscription" | ||||||
|  | 	stringMap["refund-btn"] = "Cancel Subscription" | ||||||
|  | 	stringMap["refund-badge"] = "Cancelled" | ||||||
|  |  | ||||||
|  | 	intMap := make(map[string]int) | ||||||
|  | 	intMap["is-refund"] = 0 | ||||||
|  |  | ||||||
| 	if err := app.renderTemplate(w, r, "sale", &templateData{ | 	if err := app.renderTemplate(w, r, "sale", &templateData{ | ||||||
| 		StringMap: stringMap, | 		StringMap: stringMap, | ||||||
|  | 		IntMap:    intMap, | ||||||
| 	}); err != nil { | 	}); err != nil { | ||||||
| 		app.errorLog.Println(err) | 		app.errorLog.Println(err) | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -14,6 +14,7 @@ All Subscriptions | |||||||
|             <th>Customer</th> |             <th>Customer</th> | ||||||
|             <th>Product</th> |             <th>Product</th> | ||||||
|             <th>Amount</th> |             <th>Amount</th> | ||||||
|  |             <th>Status</th> | ||||||
|         </tr> |         </tr> | ||||||
|     </thead> |     </thead> | ||||||
|     <tbody> |     <tbody> | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ | |||||||
| {{ end }} | {{ end }} | ||||||
| {{ define "content" }} | {{ define "content" }} | ||||||
| <h2 class="mt-5">Sale</h2> | <h2 class="mt-5">Sale</h2> | ||||||
| <span id="refunded" class="badge bg-danger d-none">Refunded</span> | <span id="refunded" class="badge bg-danger d-none">{{index .StringMap "refund-badge"}}</span> | ||||||
| <span id="charged" class="badge bg-success d-none">Charged</span> | <span id="charged" class="badge bg-success d-none">Charged</span> | ||||||
| <hr> | <hr> | ||||||
| <div class="alert alert-danger text-center d-none" id="messages"></div> | <div class="alert alert-danger text-center d-none" id="messages"></div> | ||||||
| @ -22,7 +22,7 @@ | |||||||
| </div> | </div> | ||||||
| <hr> | <hr> | ||||||
| <a href='{{ index .StringMap "cancel" }}' class="btn btn-info">Cancel</a> | <a href='{{ index .StringMap "cancel" }}' class="btn btn-info">Cancel</a> | ||||||
| <a id="refund-btn" href="#!" class="btn btn-warning d-none">Refund Order</a> | <a id="refund-btn" href="#!" class="btn btn-warning d-none">{{index .StringMap "refund-btn"}}</a> | ||||||
| <input type="hidden" id="pi" value=""> | <input type="hidden" id="pi" value=""> | ||||||
| <input type="hidden" id="charge-amount" value=""> | <input type="hidden" id="charge-amount" value=""> | ||||||
| <input type="hidden" id="currency" value=""> | <input type="hidden" id="currency" value=""> | ||||||
| @ -32,8 +32,10 @@ | |||||||
| <script type="module"> | <script type="module"> | ||||||
|     import {showInfo, refund} from "/static/js/sale.js" |     import {showInfo, refund} from "/static/js/sale.js" | ||||||
|     showInfo({{.API}}); |     showInfo({{.API}}); | ||||||
|  |  | ||||||
|  |     const api = {{.API}} + {{index .StringMap "refund-url"}} | ||||||
|     document.getElementById("refund-btn").addEventListener("click", function(event) { |     document.getElementById("refund-btn").addEventListener("click", function(event) { | ||||||
|         refund({{.API}}); |         refund(api, {{index .IntMap "is-refund"}}); | ||||||
|     }); |     }); | ||||||
| </script> | </script> | ||||||
| {{ end }} | {{ end }} | ||||||
|  | |||||||
| @ -135,6 +135,20 @@ func (c *Card) Refund(pi string, amount int) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *Card) CancelSubscription(subID string) error { | ||||||
|  | 	stripe.Key = c.Secret | ||||||
|  |  | ||||||
|  | 	params := &stripe.SubscriptionParams{ | ||||||
|  | 		CancelAtPeriodEnd: stripe.Bool(true), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	_, err := subscription.Update(subID, params) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func cardErrorMessage(code stripe.ErrorCode) string { | func cardErrorMessage(code stripe.ErrorCode) string { | ||||||
| 	msg := "" | 	msg := "" | ||||||
|  |  | ||||||
|  | |||||||
| @ -361,6 +361,93 @@ func (m *DBModel) GetAllOrders(isRecurring bool) ([]*Order, error) { | |||||||
| 	return orders, nil | 	return orders, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (m *DBModel) GetAllOrdersPaginated( | ||||||
|  | 	isRecurring bool, | ||||||
|  | 	pageSize, page int, | ||||||
|  | ) ([]*Order, int, int, error) { | ||||||
|  | 	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) | ||||||
|  | 	defer cancel() | ||||||
|  |  | ||||||
|  | 	offset := (page - 1) * pageSize | ||||||
|  |  | ||||||
|  | 	orders := []*Order{} | ||||||
|  |  | ||||||
|  | 	query := ` | ||||||
|  |         SELECT | ||||||
|  |             o.id, o.widget_id, o.transaction_id, o.customer_id, | ||||||
|  |             o.status_id, o.quantity, o.amount, o.created_at, o.updated_at, | ||||||
|  |             w.id, w.name, t.id, t.amount, t.currency, t.last_four, | ||||||
|  |             t.expiry_month, t.expiry_year, t.payment_intent, t.bank_return_code, | ||||||
|  |             c.id, c.first_name, c.last_name, c.email | ||||||
|  |         FROM orders o | ||||||
|  |             LEFT JOIN widgets w on (o.widget_id = w.id) | ||||||
|  |             LEFT JOIN transactions t on (o.transaction_id = t.id) | ||||||
|  |             LEFT JOIN customers c on (o.customer_id = c.id) | ||||||
|  |         WHERE | ||||||
|  |             w.is_recurring = ? | ||||||
|  |         ORDER BY | ||||||
|  |             o.created_at DESC | ||||||
|  |         LIMIT ? OFFSET ? | ||||||
|  |     ` | ||||||
|  |  | ||||||
|  | 	rows, err := m.DB.QueryContext(ctx, query, isRecurring, pageSize, offset) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, 0, 0, err | ||||||
|  | 	} | ||||||
|  | 	defer rows.Close() | ||||||
|  |  | ||||||
|  | 	for rows.Next() { | ||||||
|  | 		var o Order | ||||||
|  | 		err = rows.Scan( | ||||||
|  | 			&o.ID, | ||||||
|  | 			&o.WidgetID, | ||||||
|  | 			&o.TransactionID, | ||||||
|  | 			&o.CustomerID, | ||||||
|  | 			&o.StatusID, | ||||||
|  | 			&o.Quantity, | ||||||
|  | 			&o.Amount, | ||||||
|  | 			&o.CreatedAt, | ||||||
|  | 			&o.UpdatedAt, | ||||||
|  | 			&o.Widget.ID, | ||||||
|  | 			&o.Widget.Name, | ||||||
|  | 			&o.Transaction.ID, | ||||||
|  | 			&o.Transaction.Amount, | ||||||
|  | 			&o.Transaction.Currency, | ||||||
|  | 			&o.Transaction.LastFour, | ||||||
|  | 			&o.Transaction.ExpiryMonth, | ||||||
|  | 			&o.Transaction.ExpiryYear, | ||||||
|  | 			&o.Transaction.PaymentIntent, | ||||||
|  | 			&o.Transaction.BankReturnCode, | ||||||
|  | 			&o.Customer.ID, | ||||||
|  | 			&o.Customer.FirstName, | ||||||
|  | 			&o.Customer.LastName, | ||||||
|  | 			&o.Customer.Email, | ||||||
|  | 		) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, 0, 0, err | ||||||
|  | 		} | ||||||
|  | 		orders = append(orders, &o) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	query = ` | ||||||
|  |         SELECT COUNT(o.id) | ||||||
|  |         FROM orders o | ||||||
|  |         LEFT JOIN widgets w on (o.widget_id = w.id) | ||||||
|  |         WHERE w.is_recurring = ? | ||||||
|  |     ` | ||||||
|  |  | ||||||
|  | 	var totalRecords int | ||||||
|  | 	countRow := m.DB.QueryRowContext(ctx, query, isRecurring) | ||||||
|  | 	err = countRow.Scan(&totalRecords) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, 0, 0, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	lastPage := totalRecords / pageSize | ||||||
|  |  | ||||||
|  | 	return orders, lastPage, totalRecords, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func (m *DBModel) GetOrderByID(ID int) (Order, error) { | func (m *DBModel) GetOrderByID(ID int) (Order, error) { | ||||||
| 	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) | 	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) | ||||||
| 	defer cancel() | 	defer cancel() | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import {formatCurrency} from "./common.js" | import { formatCurrency } from "./common.js" | ||||||
|  |  | ||||||
| export function showTable(api) { | export function showTable(api) { | ||||||
|     let token = localStorage.getItem("token"); |     let token = localStorage.getItem("token"); | ||||||
| @ -17,26 +17,32 @@ export function showTable(api) { | |||||||
|         .then(response => response.json()) |         .then(response => response.json()) | ||||||
|         .then(function (data) { |         .then(function (data) { | ||||||
|             if (data) { |             if (data) { | ||||||
|             data.forEach(function (i) { |                 data.forEach(function (i) { | ||||||
|                 let newRow = tbody.insertRow(); |                     let newRow = tbody.insertRow(); | ||||||
|                 let newCell = newRow.insertCell(); |                     let newCell = newRow.insertCell(); | ||||||
|  |  | ||||||
|                 newCell.innerHTML = `<a href="/admin/subscriptions/${i.id}">Order ${i.id}</a>`; |                     newCell.innerHTML = `<a href="/admin/subscriptions/${i.id}">Order ${i.id}</a>`; | ||||||
|  |  | ||||||
|                 newCell = newRow.insertCell(); |                     newCell = newRow.insertCell(); | ||||||
|                 let item = document.createTextNode(i.customer.last_name + ", " + i.customer.first_name); |                     let item = document.createTextNode(i.customer.last_name + ", " + i.customer.first_name); | ||||||
|                 newCell.appendChild(item) |                     newCell.appendChild(item) | ||||||
|  |  | ||||||
|                 newCell = newRow.insertCell(); |                     newCell = newRow.insertCell(); | ||||||
|                 item = document.createTextNode(i.widget.name); |                     item = document.createTextNode(i.widget.name); | ||||||
|                 newCell.appendChild(item) |                     newCell.appendChild(item) | ||||||
|  |  | ||||||
|                 let cur = formatCurrency(i.transaction.amount) |                     let cur = formatCurrency(i.transaction.amount) | ||||||
|                 newCell = newRow.insertCell(); |                     newCell = newRow.insertCell(); | ||||||
|                 item = document.createTextNode(cur + "/month"); |                     item = document.createTextNode(cur + "/month"); | ||||||
|                 newCell.appendChild(item) |                     newCell.appendChild(item) | ||||||
|  |  | ||||||
|             }); |                     newCell = newRow.insertCell(); | ||||||
|  |                     if (i.status_id != 1) { | ||||||
|  |                         newCell.innerHTML = `<span class="badge bg-danger">Cancelled</span>` | ||||||
|  |                     } else { | ||||||
|  |                         newCell.innerHTML = `<span class="badge bg-success">Charged</span>` | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|             } else { |             } else { | ||||||
|                 let newRow = tbody.insertRow(); |                 let newRow = tbody.insertRow(); | ||||||
|                 let newCell = newRow.insertCell(); |                 let newCell = newRow.insertCell(); | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ export function showInfo(api) { | |||||||
|         }); |         }); | ||||||
| } | } | ||||||
|  |  | ||||||
| export function refund(api) { | export function refund(api, isRefund) { | ||||||
|     Swal.fire({ |     Swal.fire({ | ||||||
|         title: "Are you sure?", |         title: "Are you sure?", | ||||||
|         text: "You won't be able to undo this!", |         text: "You won't be able to undo this!", | ||||||
| @ -47,7 +47,7 @@ export function refund(api) { | |||||||
|         showCancelButton: true, |         showCancelButton: true, | ||||||
|         confirmButtonColor: "#3085d6", |         confirmButtonColor: "#3085d6", | ||||||
|         cancelButtonColor: "#d33", |         cancelButtonColor: "#d33", | ||||||
|         confirmButtonText: "Refund" |         confirmButtonText: isRefund === 1 ? "Refund" : "Cancel subscription" | ||||||
|     }).then((result) => { |     }).then((result) => { | ||||||
|         if (result.isConfirmed) { |         if (result.isConfirmed) { | ||||||
|             let payload = { |             let payload = { | ||||||
| @ -66,15 +66,15 @@ export function refund(api) { | |||||||
|                 body: JSON.stringify(payload), |                 body: JSON.stringify(payload), | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|             fetch(api + "/api/admin/refund", requestOptions) |             fetch(api, requestOptions) | ||||||
|                 .then(response => response.json()) |                 .then(response => response.json()) | ||||||
|                 .then(function (data) { |                 .then(function (data) { | ||||||
|                     console.log(data); |                     console.log(data); | ||||||
|                     if (!data.ok) { |                     if (!data.ok) { | ||||||
|                         showError(data.message) |                         showError("messages", data.message) | ||||||
|  |  | ||||||
|                     } else { |                     } else { | ||||||
|                         showSuccess("messages", "Refunded!") |                         showSuccess("messages",  isRefund === 1 ? "Refunded" : "Subscription cancelled") | ||||||
|                         document.getElementById("refund-btn").classList.add("d-none"); |                         document.getElementById("refund-btn").classList.add("d-none"); | ||||||
|                         document.getElementById("refunded").classList.remove("d-none"); |                         document.getElementById("refunded").classList.remove("d-none"); | ||||||
|                         document.getElementById("charged").classList.add("d-none"); |                         document.getElementById("charged").classList.add("d-none"); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user