Skip to content

Commit

Permalink
feat: endpoint to add and remove billing to company participation #298
Browse files Browse the repository at this point in the history
  • Loading branch information
bvlourenco committed Dec 27, 2022
1 parent fc07138 commit cc897ef
Show file tree
Hide file tree
Showing 12 changed files with 376 additions and 156 deletions.
3 changes: 3 additions & 0 deletions backend/src/models/company.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ type CompanyParticipation struct {
// Participation's package is a Package _id (see models.Package).
Package primitive.ObjectID `json:"package" bson:"package"`

// Participation's billing is a billing _id (see models.Billing).
Billing primitive.ObjectID `json:"billing" bson:"billing"`

Confirmed time.Time `json:"confirmed" bson:"confirmed"`

// Is this company participating as a partner.
Expand Down
3 changes: 3 additions & 0 deletions backend/src/models/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ const (
NotificationKindUpdatedParticipationPackage NotificationKind = "UPDATED_PARTICIPATION_PACKAGE"
NotificationKindDeletedParticipationPackage NotificationKind = "DELETED_PARTICIPATION_PACKAGE"

NotificationKindCreatedParticipationBilling NotificationKind = "CREATED_PARTICIPATION_BILLING"
NotificationKindDeletedParticipationBilling NotificationKind = "DELETED_PARTICIPATION_BILLING"

NotificationKindUpdatedParticipationStatus NotificationKind = "UPDATED_PARTICIPATION_STATUS"

NotificationKindTagged NotificationKind = "TAGGED"
Expand Down
64 changes: 64 additions & 0 deletions backend/src/mongodb/company.go
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,70 @@ func (c *CompaniesType) UpdatePackage(companyID primitive.ObjectID, packageID pr
return &updatedCompany, nil
}

// UpdateBilling updates the billing of a company's participation related to the current event.
// Uses a models.Billing ID to store this information.
func (c *CompaniesType) UpdateBilling(companyID primitive.ObjectID, billingID primitive.ObjectID) (*models.Company, error) {

ctx := context.Background()
currentEvent, err := Events.GetCurrentEvent()

if err != nil {
return nil, err
}

var updatedCompany models.Company

var updateQuery = bson.M{
"$set": bson.M{
"participations.$.billing": billingID,
},
}

var filterQuery = bson.M{"_id": companyID, "participations.event": currentEvent.ID}

var optionsQuery = options.FindOneAndUpdate()
optionsQuery.SetReturnDocument(options.After)

if err := c.Collection.FindOneAndUpdate(ctx, filterQuery, updateQuery, optionsQuery).Decode(&updatedCompany); err != nil {
log.Println("Error updating company's participation's billing:", err)
return nil, err
}

ResetCurrentPublicCompanies()

return &updatedCompany, nil
}

// RemoveCompanyParticipationBilling removes a billing on the company participation.
func (c *CompaniesType) RemoveCompanyParticipationBilling(companyID primitive.ObjectID) (*models.Company, error) {
ctx := context.Background()

var updatedCompany models.Company

currentEvent, err := Events.GetCurrentEvent()
if err != nil {
return nil, err
}

var updateQuery = bson.M{
"$pull": bson.M{
"participations.billing": "",
},
}

var filterQuery = bson.M{"_id": companyID, "participations.event": currentEvent.ID}

var optionsQuery = options.FindOneAndUpdate()
optionsQuery.SetReturnDocument(options.After)

if err := c.Collection.FindOneAndUpdate(ctx, filterQuery, updateQuery, optionsQuery).Decode(&updatedCompany); err != nil {
log.Println("error updating company's participation billing:", err)
return nil, err
}

return &updatedCompany, nil
}

// FindThread finds a thread in a company
func (c *CompaniesType) FindThread(threadID primitive.ObjectID) (*models.Company, error) {

Expand Down
33 changes: 0 additions & 33 deletions backend/src/router/billings.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,25 +123,6 @@ func getBilling(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(billing)
}

func createBilling(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

var cbd = &mongodb.CreateBillingData{}

if err := cbd.ParseBody(r.Body); err != nil {
http.Error(w, "Could not parse body: "+err.Error(), http.StatusBadRequest)
return
}

newBilling, err := mongodb.Billings.CreateBilling(*cbd)
if err != nil {
http.Error(w, "Error finding created billing: "+err.Error(), http.StatusNotFound)
return
}

json.NewEncoder(w).Encode(newBilling)
}

func updateBilling(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

Expand All @@ -163,17 +144,3 @@ func updateBilling(w http.ResponseWriter, r *http.Request) {

json.NewEncoder(w).Encode(newBilling)
}

func deleteBilling(w http.ResponseWriter, r *http.Request) {

params := mux.Vars(r)
billingID, _ := primitive.ObjectIDFromHex(params["id"])

billing, err := mongodb.Billings.DeleteBilling(billingID)
if err != nil {
http.Error(w, "Billing not found"+err.Error(), http.StatusNotFound)
return
}

json.NewEncoder(w).Encode(billing)
}
99 changes: 99 additions & 0 deletions backend/src/router/company.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,105 @@ func addCompanyPackage(w http.ResponseWriter, r *http.Request) {
}
}

func addCompanyParticipationBilling(w http.ResponseWriter, r *http.Request) {

defer r.Body.Close()

params := mux.Vars(r)
companyID, _ := primitive.ObjectIDFromHex(params["id"])

if _, err := mongodb.Companies.GetCompany(companyID); err != nil {
http.Error(w, "Invalid company ID", http.StatusNotFound)
return
}

var cbd = &mongodb.CreateBillingData{}

if err := cbd.ParseBody(r.Body); err != nil {
http.Error(w, "Could not parse body: "+err.Error(), http.StatusBadRequest)
return
}

newBilling, err := mongodb.Billings.CreateBilling(*cbd)
if err != nil {
http.Error(w, "Error finding created billing: "+err.Error(), http.StatusNotFound)
return
}

updatedCompany, err := mongodb.Companies.UpdateBilling(companyID, newBilling.ID)
if err != nil {
http.Error(w, "Could not update company's billing", http.StatusExpectationFailed)

// delete created billing
if _, err := mongodb.Packages.DeletePackage(newBilling.ID); err != nil {
log.Printf("error deleting billing: %s\n", err.Error())
}

return
}

json.NewEncoder(w).Encode(updatedCompany)

// notify
if credentials, ok := r.Context().Value(credentialsKey).(models.AuthorizationCredentials); ok {
mongodb.Notifications.Notify(credentials.ID, mongodb.CreateNotificationData{
Kind: models.NotificationKindCreatedParticipationBilling,
Company: &updatedCompany.ID,
})
}
}

func deleteCompanyParticipationBilling(w http.ResponseWriter, r *http.Request) {

params := mux.Vars(r)
companyID, _ := primitive.ObjectIDFromHex(params["id"])
billingID, _ := primitive.ObjectIDFromHex(params["billingID"])

if _, err := mongodb.Companies.GetCompany(companyID); err != nil {
http.Error(w, "Invalid company ID", http.StatusNotFound)
return
}

backupBilling, _ := mongodb.Billings.GetBilling(billingID)

updatedCompany, err := mongodb.Companies.RemoveCompanyParticipationBilling(companyID)
if err != nil {
http.Error(w, "Could not remove billing from company participation", http.StatusExpectationFailed)
return
}

_, err = mongodb.Billings.DeleteBilling(billingID)
if err != nil {
http.Error(w, "Billing not found"+err.Error(), http.StatusNotFound)
return
}

if err != nil {
http.Error(w, "Could not delete billing", http.StatusExpectationFailed)

if backupBilling == nil {
log.Printf("no backup billing to compensate the failed deletion of the billing: %s\n", err.Error())
}

// create deleted billing
if _, err := mongodb.Companies.UpdateBilling(companyID, billingID); err != nil {
log.Printf("error adding billing to company participation: %s\n", err.Error())
}

return
}

json.NewEncoder(w).Encode(updatedCompany)

// notify
if credentials, ok := r.Context().Value(credentialsKey).(models.AuthorizationCredentials); ok {
mongodb.Notifications.Notify(credentials.ID, mongodb.CreateNotificationData{
Kind: models.NotificationKindDeletedParticipationBilling,
Speaker: &updatedCompany.ID,
})
}
}

func deleteCompany(w http.ResponseWriter, r *http.Request) {

params := mux.Vars(r)
Expand Down
4 changes: 2 additions & 2 deletions backend/src/router/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ func InitializeRouter() {
companyRouter.HandleFunc("/{id}/participation/status/{status}", authAdmin(setCompanyStatus)).Methods("PUT")
companyRouter.HandleFunc("/{id}/participation/status/{step}", authMember(stepCompanyStatus)).Methods("POST")
companyRouter.HandleFunc("/{id}/participation/package", authCoordinator(addCompanyPackage)).Methods("POST")
companyRouter.HandleFunc("/{id}/participation/billing", authCoordinator(addCompanyParticipationBilling)).Methods("POST")
companyRouter.HandleFunc("/{id}/participation/billing/{billingID}", authCoordinator(deleteCompanyParticipationBilling)).Methods("DELETE")
companyRouter.HandleFunc("/{id}/thread", authMember(addCompanyThread)).Methods("POST")
companyRouter.HandleFunc("/{id}/employer", authMember(addEmployer)).Methods("POST")
companyRouter.HandleFunc("/{id}/employer/{rep}", authMember(removeEmployer)).Methods("DELETE")
Expand Down Expand Up @@ -311,9 +313,7 @@ func InitializeRouter() {
billingsRouter := r.PathPrefix("/billings").Subrouter()
billingsRouter.HandleFunc("", authMember(getBillings)).Methods("GET")
billingsRouter.HandleFunc("/{id}", authCoordinator(getBilling)).Methods("GET")
billingsRouter.HandleFunc("", authCoordinator(createBilling)).Methods("POST")
billingsRouter.HandleFunc("/{id}", authCoordinator(updateBilling)).Methods("PUT")
billingsRouter.HandleFunc("/{id}", authCoordinator(deleteBilling)).Methods("DELETE")

// companyReps handlers
repsRouter := r.PathPrefix("/companyReps").Subrouter()
Expand Down
2 changes: 1 addition & 1 deletion backend/static/swagger.json

Large diffs are not rendered by default.

95 changes: 0 additions & 95 deletions backend/swagger/billings.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,100 +73,5 @@
"description": "Unable to get billings"
}
}
},
"post": {
"tags": [
"billings"
],
"summary": "Creates a new billing",
"operationId": "createBilling",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"security": [
{
"Bearer": []
}
],
"parameters": [
{
"in": "body",
"name": "payload",
"description": "Information needed to create the new company.",
"required": true,
"schema": {
"type": "object",
"required": [
"status",
"event",
"value",
"invoiceNumber",
"emission",
"notes"
],
"properties": {
"status": {
"type": "object",
"required": [
"proForma",
"paid",
"receipt",
"invoice"
],
"properties": {
"proForma": {
"type": "boolean"
},
"paid": {
"type": "boolean"
},
"receipt": {
"type": "boolean"
},
"invoice": {
"type": "boolean"
}
}
},
"event": {
"type": "integer"
},
"value": {
"type": "integer"
},
"invoiceNumber": {
"type": "string"
},
"emission": {
"type": "string",
"format": "date-time"
},
"notes": {
"type": "string"
}
}
}
}
],
"responses": {
"200": {
"description": "Created billing",
"schema": {
"$ref": "./models/billing.json"
}
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Valid authorization, but not enough credentials"
},
"404": {
"description": "Couldn't find created billing"
}
}
}
}
Loading

0 comments on commit cc897ef

Please sign in to comment.