Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: fixed V2 payment history for failed payments #1900

Merged
merged 6 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions db/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,8 @@ type Bounty struct {
CodingLanguages pq.StringArray `gorm:"type:text[];not null default:'[]'" json:"coding_languages"`
PhaseUuid *string `json:"phase_uuid"`
PhasePriority *int `json:"phase_priority"`
PaymentPending bool `gorm:"default:false" json:"payment_pending"`
PaymentFailed bool `gorm:"default:false" json:"payment_failed"`
}

// Todo: Change back to Bounty
Expand Down Expand Up @@ -427,6 +429,8 @@ type NewBounty struct {
CodingLanguages pq.StringArray `gorm:"type:text[];not null default:'[]'" json:"coding_languages"`
PhaseUuid string `json:"phase_uuid"`
PhasePriority int `json:"phase_priority"`
PaymentPending bool `gorm:"default:false" json:"payment_pending"`
PaymentFailed bool `gorm:"default:false" json:"payment_failed"`
}

type BountyOwners struct {
Expand Down Expand Up @@ -718,6 +722,7 @@ type PaymentHistory struct {
ReceiverPubKey string `json:"receiver_pubkey"`
Tag string `json:"tag,omitempty"`
PaymentStatus string `json:"payment_status,omitempty"`
Error string `json:"error,omitempty"`
Created *time.Time `json:"created"`
Updated *time.Time `json:"updated"`
Status bool `json:"status"`
Expand All @@ -734,6 +739,7 @@ type NewPaymentHistory struct {
ReceiverPubKey string `json:"receiver_pubkey"`
Tag string `json:"tag,omitempty"`
PaymentStatus string `json:"payment_status,omitempty"`
Error string `json:"error,omitempty"`
Created *time.Time `json:"created"`
Updated *time.Time `json:"updated"`
Status bool `json:"status"`
Expand Down
1 change: 1 addition & 0 deletions db/structsv2.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type V2SendOnionRes struct {
Tag string `json:"tag"`
Preimage string `json:"preimage"`
PaymentHash string `json:"payment_hash"`
Message string `json:"message,omitempty"`
}

type V2PayInvoiceBody struct {
Expand Down
11 changes: 0 additions & 11 deletions db/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,17 +440,6 @@ func (db database) WithdrawBudget(sender_pubkey string, workspace_uuid string, a
func (db database) AddPaymentHistory(payment NewPaymentHistory) NewPaymentHistory {
db.db.Create(&payment)

// get Workspace budget and subtract payment from total budget
WorkspaceBudget := db.GetWorkspaceBudget(payment.WorkspaceUuid)
totalBudget := WorkspaceBudget.TotalBudget

// deduct amount if it's a bounty payment
if payment.PaymentType == "payment" {
WorkspaceBudget.TotalBudget = totalBudget - payment.Amount
}

db.UpdateWorkspaceBudget(WorkspaceBudget)

return payment
}

Expand Down
73 changes: 68 additions & 5 deletions handlers/bounty.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,22 @@ func (h *bountyHandler) CreateOrEditBounty(w http.ResponseWriter, r *http.Reques
// get bounty from DB
dbBounty := h.db.GetBounty(bounty.ID)

// check if the bounty has a pending payment
if dbBounty.PaymentPending {
msg := "You cannot update a bounty with a pending payment"
fmt.Println("[bounty]", msg)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(msg)
return
}

// trying to update
// check if bounty belongs to user
if pubKeyFromAuth != dbBounty.OwnerID {
if bounty.WorkspaceUuid != "" {
hasBountyRoles := h.userHasManageBountyRoles(pubKeyFromAuth, bounty.WorkspaceUuid)
if !hasBountyRoles {
msg := "You don't have a=the right permission ton update bounty"
msg := "You don't have the right permission ton update bounty"
fmt.Println("[bounty]", msg)
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(msg)
Expand Down Expand Up @@ -360,6 +369,12 @@ func UpdatePaymentStatus(w http.ResponseWriter, r *http.Request) {
created, _ := strconv.ParseUint(createdParam, 10, 32)

bounty, _ := db.DB.GetBountyByCreated(uint(created))
if bounty.PaymentPending {
w.WriteHeader(http.StatusBadGateway)
json.NewEncoder(w).Encode("Cannot update a bounty with a pending payment")
return
}

if bounty.ID != 0 && bounty.Created == int64(created) {
bounty.Paid = !bounty.Paid
now := time.Now()
Expand All @@ -369,6 +384,7 @@ func UpdatePaymentStatus(w http.ResponseWriter, r *http.Request) {
bounty.Completed = true
bounty.CompletionDate = &now
bounty.MarkAsPaidDate = &now

if bounty.PaidDate == nil {
bounty.PaidDate = &now
}
Expand All @@ -382,8 +398,14 @@ func UpdatePaymentStatus(w http.ResponseWriter, r *http.Request) {
func UpdateCompletedStatus(w http.ResponseWriter, r *http.Request) {
createdParam := chi.URLParam(r, "created")
created, _ := strconv.ParseUint(createdParam, 10, 32)

bounty, _ := db.DB.GetBountyByCreated(uint(created))

if bounty.PaymentPending {
w.WriteHeader(http.StatusBadGateway)
json.NewEncoder(w).Encode("Cannot update a bounty with a pending payment")
return
}

if bounty.ID != 0 && bounty.Created == int64(created) {
now := time.Now()
// set bounty as completed
Expand Down Expand Up @@ -436,6 +458,8 @@ func (h *bountyHandler) GenerateBountyResponse(bounties []db.NewBounty) []db.Bou
Updated: bounty.Updated,
CodingLanguages: bounty.CodingLanguages,
Completed: bounty.Completed,
PaymentPending: bounty.PaymentPending,
PaymentFailed: bounty.PaymentFailed,
},
Assignee: db.Person{
ID: assignee.ID,
Expand Down Expand Up @@ -531,6 +555,13 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request
return
}

if bounty.PaymentPending {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode("Bounty payemnt is pending, cannot retry payment")
h.m.Unlock()
return
}

// check if user is the admin of the workspace
// or has a pay bounty role
hasRole := h.userHasAccess(pubKeyFromAuth, bounty.WorkspaceUuid, db.PayBounty)
Expand Down Expand Up @@ -637,7 +668,7 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request
BountyId: id,
Created: &now,
Updated: &now,
Status: true,
Status: false,
PaymentType: "payment",
Tag: v2KeysendRes.Tag,
PaymentStatus: v2KeysendRes.Status,
Expand All @@ -649,6 +680,7 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request
bounty.PaidDate = &now
bounty.Completed = true
bounty.CompletionDate = &now
paymentHistory.Status = true

h.db.ProcessBountyPayment(paymentHistory, bounty)

Expand All @@ -659,10 +691,42 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request
if err == nil {
socket.Conn.WriteJSON(msg)
}

h.m.Unlock()
return
} else if v2KeysendRes.Status == db.PaymentPending {
// Send payment status
log.Printf("[bounty] V2 Status is pending: %s", v2KeysendRes.Status)
bounty.Paid = false
bounty.PaymentPending = true
bounty.PaidDate = &now
bounty.Completed = true
bounty.CompletionDate = &now
paymentHistory.Status = true

h.db.ProcessBountyPayment(paymentHistory, bounty)

msg["msg"] = "keysend_pending"
msg["invoice"] = ""

socket, err := h.getSocketConnections(request.Websocket_token)
if err == nil {
socket.Conn.WriteJSON(msg)
}

h.m.Unlock()
return
} else {
// Send payment status
log.Printf("[bounty] V2 Status Was not completed: %s", v2KeysendRes.Status)

bounty.Paid = false
bounty.PaymentPending = false
bounty.PaymentFailed = true

// set the error message
paymentHistory.Error = v2KeysendRes.Message

h.db.AddPaymentHistory(paymentHistory)

log.Println("Keysend payment not completed ===")
Expand Down Expand Up @@ -775,8 +839,6 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request
return
}
}

h.m.Unlock()
}

func (h *bountyHandler) GetBountyPaymentStatus(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -878,6 +940,7 @@ func (h *bountyHandler) UpdateBountyPaymentStatus(w http.ResponseWriter, r *http
now := time.Now()

bounty.Paid = true
bounty.PaymentPending = false
bounty.PaidDate = &now
bounty.Completed = true
bounty.CompletionDate = &now
Expand Down
1 change: 0 additions & 1 deletion routes/bounty.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ func BountyRoutes() chi.Router {
r.Post("/pay/{id}", bountyHandler.MakeBountyPayment)
r.Get("/payment/status/{id}", bountyHandler.GetBountyPaymentStatus)
r.Put("/payment/status/{id}", bountyHandler.UpdateBountyPaymentStatus)
r.Get("/payment/status/{id}", bountyHandler.GetBountyPaymentStatus)

r.Post("/", bountyHandler.CreateOrEditBounty)
r.Delete("/assignee", handlers.DeleteBountyAssignee)
Expand Down
Loading