<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sgeddam2</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sgeddam2"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Sgeddam2"/>
	<updated>2026-05-20T06:59:06Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=150000</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=150000"/>
		<updated>2023-04-24T15:40:40Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Project Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===1. Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===2. Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===3. Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===4. Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===5. We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
The file invitation.rb defines the Invitation model which is a subclass of ApplicationRecord. The Invitation model has three foreign keys. to_user represents the user to whom the inviations is sent. from_user represents the user who is creating the invitation. assignment represents which assignment the invitation belongs to. reply_status represents whether the invitation is accepted, rejected or waiting. The default reply_status is waiting 'W'. There are also multiple validations defined for the various fields in this model. One of the important validation is to_from_cant_be_same validation, which prevents users from creating invitations to themselves. Moreover there are multiple helper methods defined for Invitations. These methods help keep the controller code short and clean. We are following the rails philosophy of &amp;quot;Fat Models&amp;quot;. For the scope of this project the helper methods are kept simple, however once the project advances these helper methods need to be updated. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
  after_initialize :set_defaults&lt;br /&gt;
&lt;br /&gt;
  ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
  REJECT_STATUS = 'R'.freeze&lt;br /&gt;
  WAITING_STATUS = 'W'.freeze&lt;br /&gt;
&lt;br /&gt;
  belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
  belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
  belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
  validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
  validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
  validates :assignment_id, uniqueness: {&lt;br /&gt;
    scope: %i[from_id to_id reply_status],&lt;br /&gt;
    message: 'You cannot have duplicate invitations'&lt;br /&gt;
  }&lt;br /&gt;
  validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
  # validate if the to_id and from_id are same&lt;br /&gt;
  def to_from_cant_be_same&lt;br /&gt;
    return unless from_id == to_id&lt;br /&gt;
&lt;br /&gt;
    errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # Return a new invitation&lt;br /&gt;
  # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
  def self.invitation_factory(params)&lt;br /&gt;
    Invitation.new(params)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # check if the user is invited&lt;br /&gt;
  def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
    @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                   .where(from_id:)&lt;br /&gt;
                                   .where(assignment_id:)&lt;br /&gt;
                                   .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                   .count&lt;br /&gt;
    @invitations_count.positive?&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # send invite email&lt;br /&gt;
  def send_invite_email&lt;br /&gt;
    InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                        .send_invitation_email&lt;br /&gt;
                        .deliver_later&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
  # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
  def update_users_topic_after_invite_accept(_inviter_user_id, _invited_user_id, _assignment_id); end&lt;br /&gt;
&lt;br /&gt;
  # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
  # Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
  # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
  # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
  # Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
  # NOTE: For now this method simply updates the invitation's reply_status.&lt;br /&gt;
  def accept_invitation(_logged_in_user)&lt;br /&gt;
    update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This method handles all that needs to be done upon an user declining an invitation.&lt;br /&gt;
  def decline_invitation(_logged_in_user)&lt;br /&gt;
    update(reply_status: REJECT_STATUS)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
  def retract_invitation(_logged_in_user)&lt;br /&gt;
    destroy&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
  def as_json(options = {})&lt;br /&gt;
    super(options.merge({&lt;br /&gt;
                          only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                          include: {&lt;br /&gt;
                            assignment: { only: %i[id name] },&lt;br /&gt;
                            from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                            to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                          }&lt;br /&gt;
                        })).tap do |hash|&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def set_defaults&lt;br /&gt;
    self.reply_status ||= WAITING_STATUS&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
Validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
Check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
A user can have many invitations therefore we added a has_many relationship in the user model. On the other hand in the invitation model we added belongs_to relationship with the user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
An assignment can have many invitations therefore we added a has_many relationship in the assignment model. On the other hand in the invitation model we added belongs_to relationship with the assignment model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The invitation schema has three foreign keys. The foreign keys are &amp;quot;assignment_id&amp;quot;, &amp;quot;from_id&amp;quot;, &amp;quot;to_id&amp;quot;. from_id and to_id are foreign keys to user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||{ &amp;lt;br/&amp;gt; &amp;quot;assignment_id&amp;quot;: INT, &amp;lt;br/&amp;gt; &amp;quot;from_id&amp;quot;: INT, &amp;lt;br/&amp;gt; &amp;quot;to_id&amp;quot;: INT, &amp;lt;br/&amp;gt; &amp;quot;reply_status&amp;quot;: CHAR&amp;lt;br/&amp;gt;} ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || { &amp;lt;br/&amp;gt;&amp;quot;reply_status&amp;quot;:[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] &amp;lt;br/&amp;gt; } || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Our tests covers 100% of the lines in the Invitation model.&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
* [https://youtu.be/nSSuKuOaFWE Demo Video]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam [sgeddam2]&lt;br /&gt;
* Keerthana Telaprolu [ktelapr]&lt;br /&gt;
* Dhrumil Shah [dshah6]&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra [amundra]&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149999</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149999"/>
		<updated>2023-04-24T15:30:25Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* End point summary */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===1. Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===2. Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===3. Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===4. Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===5. We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: Waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: Accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: Rejected&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
Validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
Check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
A user can have many invitations therefore we added a has_many relationship in the user model. On the other hand in the invitation model we added belongs_to relationship with the user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
An assignment can have many invitations therefore we added a has_many relationship in the assignment model. On the other hand in the invitation model we added belongs_to relationship with the assignment model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The invitation schema has three foreign keys. The foreign keys are &amp;quot;assignment_id&amp;quot;, &amp;quot;from_id&amp;quot;, &amp;quot;to_id&amp;quot;. from_id and to_id are foreign keys to user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||{ &amp;lt;br/&amp;gt; &amp;quot;assignment_id&amp;quot;: INT, &amp;lt;br/&amp;gt; &amp;quot;from_id&amp;quot;: INT, &amp;lt;br/&amp;gt; &amp;quot;to_id&amp;quot;: INT, &amp;lt;br/&amp;gt; &amp;quot;reply_status&amp;quot;: CHAR&amp;lt;br/&amp;gt;} ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || { &amp;lt;br/&amp;gt;&amp;quot;reply_status&amp;quot;:[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] &amp;lt;br/&amp;gt; } || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Our tests covers 100% of the lines in the Invitation model.&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
* [https://youtu.be/nSSuKuOaFWE Demo Video]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam [sgeddam2]&lt;br /&gt;
* Keerthana Telaprolu [ktelapr]&lt;br /&gt;
* Dhrumil Shah [dshah6]&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra [amundra]&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149998</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149998"/>
		<updated>2023-04-24T15:26:31Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Project Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===1. Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===2. Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===3. Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===4. Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===5. We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: Waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: Accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: Rejected&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
Validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
Check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
A user can have many invitations therefore we added a has_many relationship in the user model. On the other hand in the invitation model we added belongs_to relationship with the user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
An assignment can have many invitations therefore we added a has_many relationship in the assignment model. On the other hand in the invitation model we added belongs_to relationship with the assignment model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The invitation schema has three foreign keys. The foreign keys are &amp;quot;assignment_id&amp;quot;, &amp;quot;from_id&amp;quot;, &amp;quot;to_id&amp;quot;. from_id and to_id are foreign keys to user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Our tests covers 100% of the lines in the Invitation model.&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
* [https://youtu.be/nSSuKuOaFWE Demo Video]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam [sgeddam2]&lt;br /&gt;
* Keerthana Telaprolu [ktelapr]&lt;br /&gt;
* Dhrumil Shah [dshah6]&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra [amundra]&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149997</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149997"/>
		<updated>2023-04-24T15:25:46Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Helper Methods in Invitation model. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===1. Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===2. Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===3. Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===4. Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===5. We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
Validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
Check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
A user can have many invitations therefore we added a has_many relationship in the user model. On the other hand in the invitation model we added belongs_to relationship with the user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
An assignment can have many invitations therefore we added a has_many relationship in the assignment model. On the other hand in the invitation model we added belongs_to relationship with the assignment model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The invitation schema has three foreign keys. The foreign keys are &amp;quot;assignment_id&amp;quot;, &amp;quot;from_id&amp;quot;, &amp;quot;to_id&amp;quot;. from_id and to_id are foreign keys to user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Our tests covers 100% of the lines in the Invitation model.&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
* [https://youtu.be/nSSuKuOaFWE Demo Video]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam [sgeddam2]&lt;br /&gt;
* Keerthana Telaprolu [ktelapr]&lt;br /&gt;
* Dhrumil Shah [dshah6]&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra [amundra]&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149996</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149996"/>
		<updated>2023-04-24T15:23:30Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Helper Methods in Invitation model. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===1. Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===2. Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===3. Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===4. Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===5. We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
A user can have many invitations therefore we added a has_many relationship in the user model. On the other hand in the invitation model we added belongs_to relationship with the user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
An assignment can have many invitations therefore we added a has_many relationship in the assignment model. On the other hand in the invitation model we added belongs_to relationship with the assignment model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The invitation schema has three foreign keys. The foreign keys are &amp;quot;assignment_id&amp;quot;, &amp;quot;from_id&amp;quot;, &amp;quot;to_id&amp;quot;. from_id and to_id are foreign keys to user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Our tests covers 100% of the lines in the Invitation model.&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
* [https://youtu.be/nSSuKuOaFWE Demo Video]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam [sgeddam2]&lt;br /&gt;
* Keerthana Telaprolu [ktelapr]&lt;br /&gt;
* Dhrumil Shah [dshah6]&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra [amundra]&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149995</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149995"/>
		<updated>2023-04-24T15:22:48Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Screen Shots */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===1. Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===2. Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===3. Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===4. Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===5. We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
A user can have many invitations therefore we added a has_many relationship in the user model. On the other hand in the invitation model we added belongs_to relationship with the user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
An assignment can have many invitations therefore we added a has_many relationship in the assignment model. On the other hand in the invitation model we added belongs_to relationship with the assignment model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The invitation schema has three foreign keys. The foreign keys are &amp;quot;assignment_id&amp;quot;, &amp;quot;from_id&amp;quot;, &amp;quot;to_id&amp;quot;. from_id and to_id are foreign keys to user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Our tests covers 100% of the lines in the Invitation model.&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
* [https://youtu.be/nSSuKuOaFWE Demo Video]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam [sgeddam2]&lt;br /&gt;
* Keerthana Telaprolu [ktelapr]&lt;br /&gt;
* Dhrumil Shah [dshah6]&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra [amundra]&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149994</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149994"/>
		<updated>2023-04-24T15:20:41Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Helper Methods in Invitation model. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
A user can have many invitations therefore we added a has_many relationship in the user model. On the other hand in the invitation model we added belongs_to relationship with the user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
An assignment can have many invitations therefore we added a has_many relationship in the assignment model. On the other hand in the invitation model we added belongs_to relationship with the assignment model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
The invitation schema has three foreign keys. The foreign keys are &amp;quot;assignment_id&amp;quot;, &amp;quot;from_id&amp;quot;, &amp;quot;to_id&amp;quot;. from_id and to_id are foreign keys to user model.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Our tests covers 100% of the lines in the Invitation model.&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
* [https://youtu.be/nSSuKuOaFWE Demo Video]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam [sgeddam2]&lt;br /&gt;
* Keerthana Telaprolu [ktelapr]&lt;br /&gt;
* Dhrumil Shah [dshah6]&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra [amundra]&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149991</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149991"/>
		<updated>2023-04-24T13:49:08Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Testing Plan */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Our tests covers 100% of the lines in the Invitation model.&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
* [https://youtu.be/nSSuKuOaFWE Demo Video]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam [sgeddam2]&lt;br /&gt;
* Keerthana Telaprolu [ktelapr]&lt;br /&gt;
* Dhrumil Shah [dshah6]&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra [amundra]&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149907</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149907"/>
		<updated>2023-04-24T01:30:28Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Mentor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
* [https://youtu.be/nSSuKuOaFWE Demo Video]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam [sgeddam2]&lt;br /&gt;
* Keerthana Telaprolu [ktelapr]&lt;br /&gt;
* Dhrumil Shah [dshah6]&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra [amundra]&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149906</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149906"/>
		<updated>2023-04-24T01:30:04Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Team Members */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
* [https://youtu.be/nSSuKuOaFWE Demo Video]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam [sgeddam2]&lt;br /&gt;
* Keerthana Telaprolu [ktelapr]&lt;br /&gt;
* Dhrumil Shah [dshah6]&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149905</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149905"/>
		<updated>2023-04-24T01:29:17Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
* [https://youtu.be/nSSuKuOaFWE Demo Video]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149881</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149881"/>
		<updated>2023-04-23T15:05:07Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [Future work]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149880</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149880"/>
		<updated>2023-04-23T15:04:40Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* check_user_before_invitation [Not in scope of this project]: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149879</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149879"/>
		<updated>2023-04-23T15:04:30Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* check_participant_before_invitation [Not in scope of this project]: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149878</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149878"/>
		<updated>2023-04-23T15:04:19Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* check_team_before_invitation [Not in scope of this project]: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Future work]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149877</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149877"/>
		<updated>2023-04-23T15:04:07Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* check_team_before_accept [Not in scope of this project]: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Future work]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149876</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149876"/>
		<updated>2023-04-23T15:03:08Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* check_participant_before_invitation [Not in scope of this project]: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149875</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149875"/>
		<updated>2023-04-23T15:02:58Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* check_participant_before_invitation [Not in scope of this project]: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
his method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149874</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149874"/>
		<updated>2023-04-23T15:02:42Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* check_user_before_invitation [Not in scope of this project]: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.Additionally, this method will also check if the sender himself is participating in the given assignment before they can  send an invitation.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149873</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149873"/>
		<updated>2023-04-23T15:02:03Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* check_participant_before_invitation [Not in scope of this project]: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.Additionally, this method will also check if the sender himself is participating in the given assignment before they can  send an invitation.&lt;br /&gt;
&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149872</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149872"/>
		<updated>2023-04-23T15:01:07Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* check_team_before_accept [Not in scope of this project]: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149871</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149871"/>
		<updated>2023-04-23T14:59:49Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is accepted.&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Files modified/created =&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_APP.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_DB.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png|300px]]&lt;br /&gt;
&lt;br /&gt;
[[File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png|300px]]&lt;br /&gt;
&lt;br /&gt;
=Future Work=&lt;br /&gt;
&lt;br /&gt;
Implement methods in invitation_controller.rb and invitation.rb. Some of the methods were not implemented due to dependency on other models which are not implemented yet. The dependency models need to be implemented first and then these methods can be implemented. We have left out the placeholder in the source code for such methods and a small explaination of what is expected from the future implementation of the method.&lt;br /&gt;
&lt;br /&gt;
Authentication system is required for the working of invitation feature. Before performing any action related to invitation, authorization of the request must be done to make sure the user is able to perform the action requested. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation_controller.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;check_invited_user_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user exists. Additionally, this method will also check if the sender himself is participating in the given assignment before they can send an invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_participant_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;check_team_before_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is being accepted for example check if the invite's team is still existing, and have available slot to add the invitee.&lt;br /&gt;
&lt;br /&gt;
===== Future work in invitation.rb =====&lt;br /&gt;
&amp;lt;pre&amp;gt;update_users_topic_after_invite_accept&amp;lt;/pre&amp;gt;&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;accept_invitation&amp;lt;/pre&amp;gt;&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
Expected functionality: First the users previous team is deleted if they were the only member of that&lt;br /&gt;
team and topics that the old team signed up for will be deleted.&lt;br /&gt;
Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
Lastly the users team entry will be added to the TeamsUser table and their assigned topic is updated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png&amp;diff=149870</id>
		<title>File:ROHIT GEDDAM FILES CHANGED SWAGGER.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_FILES_CHANGED_SWAGGER.png&amp;diff=149870"/>
		<updated>2023-04-23T14:19:24Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png&amp;diff=149869</id>
		<title>File:ROHIT GEDDAM FILES CHANGED SPEC.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_FILES_CHANGED_SPEC.png&amp;diff=149869"/>
		<updated>2023-04-23T14:19:05Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_FILES_CHANGED_DB.png&amp;diff=149868</id>
		<title>File:ROHIT GEDDAM FILES CHANGED DB.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_FILES_CHANGED_DB.png&amp;diff=149868"/>
		<updated>2023-04-23T14:18:32Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png&amp;diff=149867</id>
		<title>File:ROHIT GEDDAM FILES CHANGED CONFIG.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_FILES_CHANGED_CONFIG.png&amp;diff=149867"/>
		<updated>2023-04-23T14:18:03Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_FILES_CHANGED_APP.png&amp;diff=149866</id>
		<title>File:ROHIT GEDDAM FILES CHANGED APP.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_FILES_CHANGED_APP.png&amp;diff=149866"/>
		<updated>2023-04-23T14:17:26Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149853</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149853"/>
		<updated>2023-04-22T17:39:48Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Remove all invites sent by a user for an assignment.&lt;br /&gt;
 def remove_users_sent_invites_for_assignment(user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====remove_users_sent_invites_for_assignment(user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
Removes all invites sent by a user for an assignment. This method can be useful&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is accepted.&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/api-docs/ Swagger UI]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149852</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149852"/>
		<updated>2023-04-22T17:13:04Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Helper Methods in Invitation model. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Remove all invites sent by a user for an assignment.&lt;br /&gt;
 def remove_users_sent_invites_for_assignment(user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====remove_users_sent_invites_for_assignment(user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
Removes all invites sent by a user for an assignment. This method can be useful&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the user.rb file.&lt;br /&gt;
&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# added the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is accepted.&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149851</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149851"/>
		<updated>2023-04-22T17:11:31Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Screen Shots */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
===Send an invite ===&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Accept an invite===&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Reject invite===&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Retract invite===&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===We retracted invitation of angel and malka and added ofelia===&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Remove all invites sent by a user for an assignment.&lt;br /&gt;
 def remove_users_sent_invites_for_assignment(user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====remove_users_sent_invites_for_assignment(user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
Removes all invites sent by a user for an assignment. This method can be useful&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# add the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is accepted.&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149850</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149850"/>
		<updated>2023-04-22T17:09:14Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Model Tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
====send an invite ====&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== accept an invite ====&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== reject invite ====&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== retract invite ====&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== we retracted invitation of angel and malka and added ofelia ====&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Remove all invites sent by a user for an assignment.&lt;br /&gt;
 def remove_users_sent_invites_for_assignment(user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====remove_users_sent_invites_for_assignment(user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
Removes all invites sent by a user for an assignment. This method can be useful&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# add the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is accepted.&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Test Coverage Report for Invitation model.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_test_coverage.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_Invitation_test_coverage.png&amp;diff=149849</id>
		<title>File:ROHIT GEDDAM Invitation test coverage.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_Invitation_test_coverage.png&amp;diff=149849"/>
		<updated>2023-04-22T17:08:04Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: Screenshot showing test coverage of invitation.rb&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Screenshot showing test coverage of invitation.rb&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149848</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149848"/>
		<updated>2023-04-22T17:06:14Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Model Tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
====send an invite ====&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== accept an invite ====&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== reject invite ====&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== retract invite ====&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== we retracted invitation of angel and malka and added ofelia ====&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Remove all invites sent by a user for an assignment.&lt;br /&gt;
 def remove_users_sent_invites_for_assignment(user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====remove_users_sent_invites_for_assignment(user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
Removes all invites sent by a user for an assignment. This method can be useful&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# add the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is accepted.&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:ROHIT_GEDDAM_Invitation_spec.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_Invitation_spec.png&amp;diff=149847</id>
		<title>File:ROHIT GEDDAM Invitation spec.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:ROHIT_GEDDAM_Invitation_spec.png&amp;diff=149847"/>
		<updated>2023-04-22T17:05:38Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: Invitation spec screenshot&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Invitation spec screenshot&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149846</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149846"/>
		<updated>2023-04-22T17:01:23Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Controller Tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
====send an invite ====&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== accept an invite ====&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== reject invite ====&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== retract invite ====&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== we retracted invitation of angel and malka and added ofelia ====&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Remove all invites sent by a user for an assignment.&lt;br /&gt;
 def remove_users_sent_invites_for_assignment(user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====remove_users_sent_invites_for_assignment(user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
Removes all invites sent by a user for an assignment. This method can be useful&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# add the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is accepted.&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/requests/api/v1/invitation_controller_spec.rb invitation_controller_spec.rb]&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_test2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149845</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149845"/>
		<updated>2023-04-22T16:57:42Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Model Tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
====send an invite ====&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== accept an invite ====&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== reject invite ====&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== retract invite ====&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== we retracted invitation of angel and malka and added ofelia ====&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Remove all invites sent by a user for an assignment.&lt;br /&gt;
 def remove_users_sent_invites_for_assignment(user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====remove_users_sent_invites_for_assignment(user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
Removes all invites sent by a user for an assignment. This method can be useful&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# add the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is accepted.&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
File: [https://github.com/rohitgeddam/reimplementation-back-end/blob/main/spec/models/invitation_spec.rb invitation_spec.rb]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_test2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149844</id>
		<title>CSC/ECE 517 Spring 2023 - E2330. Reimplement Invitation Controller</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2023_-_E2330._Reimplement_Invitation_Controller&amp;diff=149844"/>
		<updated>2023-04-22T16:51:21Z</updated>

		<summary type="html">&lt;p&gt;Sgeddam2: /* Model Tests */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Project Overview==&lt;br /&gt;
&lt;br /&gt;
===Expertiza Background===&lt;br /&gt;
&lt;br /&gt;
Expertiza is an online platform designed to facilitate peer review and submission of various types of academic work, including articles, codes, and websites. The application allows instructors to add assignments, grade them, and assign students to teams based on their topic preferences. The platform also enables students to provide feedback on each other's work through peer reviews, which can be helpful in improving the quality of their projects. Expertiza is backed by the National Science Foundation.&lt;br /&gt;
&lt;br /&gt;
===Problem Statement===&lt;br /&gt;
&lt;br /&gt;
The Invitation model and InvitationsController are responsible for managing invitations between users in a team-based assignment system. The system allows a student to invite another student to their team by creating a new Invitation record, which is associated with the inviting and invited students and the assignment they are working on. The invited user can accept, decline, or cancel the invitation, which updates the corresponding Invitation record and may trigger actions such as adding or removing users from teams. The InvitationsController includes methods for creating, accepting, declining, and canceling invitations, as well as checking the status of the user and team before sending or accepting invitations. The system also sends email notifications to invited users when a new invitation is sent. Overall, the Invitation model and InvitationsController are crucial for managing team membership and collaboration in a team-based assignment system.  Instructor’s note: There is already a project to merge this controller with the join_team_requests_controller.  You should start with the code they have written.&lt;br /&gt;
&lt;br /&gt;
==Objectives==&lt;br /&gt;
1. Write RESTful endpoints of create, show, delete to invitations and approving new invitations, listing pending invitations, creating new invitations, and notifying students about new team formation invite.&lt;br /&gt;
&lt;br /&gt;
2. Develop and implement methods in the InvitationsController that enable the following functionality:Create invitations, Accept invitations, Decline invitations, Cancel invitations, and Check user and team status before sending or accepting invitations.&lt;br /&gt;
&lt;br /&gt;
3. To implement a user-invitation system that allows invited users to accept, decline, or cancel invitations, which will update the corresponding Invitation record and trigger actions such as adding or removing users from teams.&lt;br /&gt;
&lt;br /&gt;
4. Implement an email notification system in the user-invitation system, which sends email notifications to invited users when a new invitation is sent.&lt;br /&gt;
&lt;br /&gt;
5. Return proper status codes and proper validation for RESTful endpoints.&lt;br /&gt;
&lt;br /&gt;
6. Write models and controllers such that they use modern approaches to writing Ruby code, including utilizing language features and adhering to best practices for object-oriented design.&lt;br /&gt;
&lt;br /&gt;
7. Write proper Rspec tests for all APIs, models, controllers.&lt;br /&gt;
&lt;br /&gt;
== Development Strategy ==&lt;br /&gt;
&lt;br /&gt;
We have tried to follow a Test Driven Development approach to implement both the Invitation model and the Invitation Controller.&lt;br /&gt;
Firstly a failing test case was written and then the code was added such that the test which was failing will pass now.&lt;br /&gt;
&lt;br /&gt;
Also, we have tried to follow the rails philosophy of &amp;quot;Fat models&amp;quot; We have tried to move as much business logic from the controller to the model as possible. This will also help keep the controller code clean and encourage code reusability.&lt;br /&gt;
&lt;br /&gt;
==Project Design and Implementation==&lt;br /&gt;
&lt;br /&gt;
===Use Case Diagram ===&lt;br /&gt;
[[File:Usecasediagram1.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Class Diagram ===&lt;br /&gt;
[[File:dshah6_UML_Diagram.png|900px]]&lt;br /&gt;
&lt;br /&gt;
===Functionality===&lt;br /&gt;
In this project, we aim to add the following functions:&lt;br /&gt;
&lt;br /&gt;
1. Enable users to create a new team invitation.&lt;br /&gt;
&lt;br /&gt;
2. Enable users to Accept or Reject invitations.&lt;br /&gt;
&lt;br /&gt;
3. Enable users to Retract invitations.&lt;br /&gt;
&lt;br /&gt;
4. Enable users to send email notifications to invited users.&lt;br /&gt;
&lt;br /&gt;
5. Ensure that data is validated properly in all the above APIs.&lt;br /&gt;
&lt;br /&gt;
6. Test cases for all the above.&lt;br /&gt;
&lt;br /&gt;
==Screen Shots==&lt;br /&gt;
====send an invite ====&lt;br /&gt;
[[File:Dshah6_send_invite.png|900px]]&lt;br /&gt;
[[File:Dshah6_send_invite_2.png|900px]]&lt;br /&gt;
[[File:Dshah6_send_invite_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== accept an invite ====&lt;br /&gt;
[[File:Dshah6_accept_1.png|900px]]&lt;br /&gt;
[[File:Dshah6_accept_2.png|900px]]&lt;br /&gt;
[[File:Dshah6_accept_3.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== reject invite ====&lt;br /&gt;
[[File:Dshah6_decline_1.png|900px]]&lt;br /&gt;
[[File:Dshah6_decline_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== retract invite ====&lt;br /&gt;
[[File:Dshah6_retract_1.png|900px]]&lt;br /&gt;
&lt;br /&gt;
==== we retracted invitation of angel and malka and added ofelia ====&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_retract_2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
= Project Design =&lt;br /&gt;
&lt;br /&gt;
===Model===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;W: waiting&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;A: accepted&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;R: rejected/declined&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: invitation.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/invitation.rb  GitHub file Link to invitation.rb]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class Invitation &amp;lt; ApplicationRecord&lt;br /&gt;
 after_initialize :set_defaults&lt;br /&gt;
 ACCEPT_STATUS = 'A'.freeze&lt;br /&gt;
 REJECT_STATUS = 'R'.freeze&lt;br /&gt;
 WAITING_STATUS = 'W'.freeze&lt;br /&gt;
 belongs_to :to_user, class_name: 'User', foreign_key: 'to_id', inverse_of: false&lt;br /&gt;
 belongs_to :from_user, class_name: 'User', foreign_key: 'from_id', inverse_of: false&lt;br /&gt;
 belongs_to :assignment, class_name: 'Assignment', foreign_key: 'assignment_id'&lt;br /&gt;
 validates :reply_status, presence: true, length: { maximum: 1 }&lt;br /&gt;
 validates_inclusion_of :reply_status, in: [ACCEPT_STATUS, REJECT_STATUS, WAITING_STATUS], allow_nil: false&lt;br /&gt;
 validates :assignment_id, uniqueness: {&lt;br /&gt;
   scope: %i[from_id to_id reply_status],&lt;br /&gt;
   message: 'You cannot have duplicate invitations'&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 validate :to_from_cant_be_same&lt;br /&gt;
&lt;br /&gt;
 # validate if the to_id and from_id are same&lt;br /&gt;
 def to_from_cant_be_same&lt;br /&gt;
   return unless from_id == to_id&lt;br /&gt;
   errors.add(:from_id, 'to and from users should be different')&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Return a new invitation&lt;br /&gt;
 # params = :assignment_id, :to_id, :from_id, :reply_status&lt;br /&gt;
 def self.invitation_factory(params)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   Invitation.new(params)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # check if the user is invited&lt;br /&gt;
 def self.invited?(from_id, to_id, assignment_id)&lt;br /&gt;
   @invitations_count = Invitation.where(to_id:)&lt;br /&gt;
                                  .where(from_id:)&lt;br /&gt;
                                  .where(assignment_id:)&lt;br /&gt;
                                  .where(reply_status: WAITING_STATUS)&lt;br /&gt;
                                  .count&lt;br /&gt;
   @invitations_count.positive?&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # send invite email&lt;br /&gt;
 def send_invite_email&lt;br /&gt;
   InvitationSentMailer.with(invitation: self)&lt;br /&gt;
                       .send_invitation_email&lt;br /&gt;
                       .deliver_later&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # Remove all invites sent by a user for an assignment.&lt;br /&gt;
 def remove_users_sent_invites_for_assignment(user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
 # NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
 def update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id); end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
 # First the users previous team is deleted if they were the only member of that&lt;br /&gt;
 # team and topics that the old team signed up for will be deleted.&lt;br /&gt;
 # Then invites the user that accepted the invite sent will be removed.&lt;br /&gt;
 # Last the users team entry will be added to the TeamsUser table and their assigned topic is updated&lt;br /&gt;
 def accept_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: ACCEPT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
 def decline_invitation(logged_in_user)&lt;br /&gt;
   update(reply_status: REJECT_STATUS)&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
 def retract_invitation(logged_in_user)&lt;br /&gt;
   destroy&lt;br /&gt;
 end&lt;br /&gt;
&lt;br /&gt;
 # This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
 def as_json(options = {})&lt;br /&gt;
   super(options.merge({&lt;br /&gt;
                         only: %i[id reply_status created_at updated_at],&lt;br /&gt;
                         include: {&lt;br /&gt;
                           assignment: { only: %i[id name] },&lt;br /&gt;
                           from_user: { only: %i[id name fullname email] },&lt;br /&gt;
                           to_user: { only: %i[id name fullname email] }&lt;br /&gt;
                         }&lt;br /&gt;
                       })).tap do |hash|&lt;br /&gt;
   end&lt;br /&gt;
 end&lt;br /&gt;
 def set_defaults&lt;br /&gt;
   self.reply_status ||= WAITING_STATUS&lt;br /&gt;
 end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Helper Methods in Invitation model.===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====to_from_cant_be_same:====&lt;br /&gt;
validate if the to_id and from_id are same i.e a users cannot send invitations to themselves.&lt;br /&gt;
&lt;br /&gt;
====self.invitation_factory(params):====&lt;br /&gt;
This helper method will help in creating new Invitation with the given parameters. Custom parameters can be passed to create specific Invitation.&lt;br /&gt;
&lt;br /&gt;
====self.invited?(from_id, to_id, assignment_id):====&lt;br /&gt;
check if the user is invited given the from_id, to_id, and assignment_id. This is a class method to make it more generic and can be used by other classes.&lt;br /&gt;
&lt;br /&gt;
====send_invite_email:====&lt;br /&gt;
This method uses the InvitaionSentMailer to send invitation emails to the invited user.&lt;br /&gt;
&lt;br /&gt;
====remove_users_sent_invites_for_assignment(user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
Removes all invites sent by a user for an assignment. This method can be useful&lt;br /&gt;
&lt;br /&gt;
====update_users_topic_after_invite_accept(inviter_user_id, invited_user_id, assignment_id) [ OUT OF SCOPE OF THIS PROJECT ]:====&lt;br /&gt;
After a users accepts an invite, the teams_users table needs to be updated.&lt;br /&gt;
NOTE: Depends on TeamUser model, which is not implemented yet.&lt;br /&gt;
&lt;br /&gt;
====accept_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon a user accepting an invitation.&lt;br /&gt;
&lt;br /&gt;
====decline_invitation:====&lt;br /&gt;
This method handles all that needs to be done upon an user decline an invitation.&lt;br /&gt;
&lt;br /&gt;
====retract_invitation:====&lt;br /&gt;
This method handles all that need to be done upon an invitation retraction.&lt;br /&gt;
&lt;br /&gt;
====as_json:====&lt;br /&gt;
This will override the default as_json method in the ApplicationRecord class and specify&lt;br /&gt;
&lt;br /&gt;
====set_defaults:====&lt;br /&gt;
This will be used to set default parameters when creating new Invitation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/user.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/user.rb GitHub Link to user.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
has_many :invitations&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Changes in models/assignment.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/models/assignment.rb GitHub Link to assignment.rb file]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# add the following relations in the assignment.rb file.&lt;br /&gt;
&lt;br /&gt;
class Assignment &amp;lt; ApplicationRecord&lt;br /&gt;
 	has_many :invitations&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Schema&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;filename: schema.rb&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/db/schema.rb GitHub Link to scheme.rb file]&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  create_table &amp;quot;invitations&amp;quot;, charset: &amp;quot;utf8mb4&amp;quot;, collation: &amp;quot;utf8mb4_0900_ai_ci&amp;quot;, force: :cascade do |t|&lt;br /&gt;
    t.integer &amp;quot;assignment_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;from_id&amp;quot;&lt;br /&gt;
    t.integer &amp;quot;to_id&amp;quot;&lt;br /&gt;
    t.string &amp;quot;reply_status&amp;quot;, limit: 1&lt;br /&gt;
    t.datetime &amp;quot;created_at&amp;quot;, null: false&lt;br /&gt;
    t.datetime &amp;quot;updated_at&amp;quot;, null: false&lt;br /&gt;
    t.index [&amp;quot;assignment_id&amp;quot;], name: &amp;quot;fk_invitation_assignments&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;from_id&amp;quot;], name: &amp;quot;fk_invitationfrom_users&amp;quot;&lt;br /&gt;
    t.index [&amp;quot;to_id&amp;quot;], name: &amp;quot;fk_invitationto_users&amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Controllers===&lt;br /&gt;
We create a new controller at app/controllers/invitation_controller.rb with following methods:&lt;br /&gt;
[Implementation of the invitation controller[https://github.com/rohitgeddam/reimplementation-back-end/blob/main/app/controllers/api/v1/invitations_controller.rb]]&lt;br /&gt;
===REST Route methods===&lt;br /&gt;
=====create:=====&lt;br /&gt;
This will create a new invitation record.&lt;br /&gt;
=====index:=====&lt;br /&gt;
This will give a list of all the invitations&lt;br /&gt;
=====show:=====&lt;br /&gt;
This will be used to show a particular invitation with given invitation_id.&lt;br /&gt;
=====update:=====&lt;br /&gt;
This will be used to update the status of the current invitation. Either accepted or rejected&lt;br /&gt;
=====destroy:=====&lt;br /&gt;
This will be used to delete the invitation that is already sent to another participant using particular invite_id.&lt;br /&gt;
=====invitations_for_user_assignment:=====&lt;br /&gt;
This will be used to get all the invitations for a particular assignment for a particular student.&lt;br /&gt;
&lt;br /&gt;
=== Helper methods ===&lt;br /&gt;
=====check_team_before_accept [Not in scope of this project]:===== &lt;br /&gt;
This method will check if the team meets the joining requirements when an invitation is accepted.&lt;br /&gt;
=====check_team_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the team meets the joining requirement before sending an invite.&lt;br /&gt;
=====check_participant_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user is a participant in the assignment.&lt;br /&gt;
=====check_user_before_invitation [Not in scope of this project]:=====&lt;br /&gt;
This method will check if the invited user exists.&lt;br /&gt;
&lt;br /&gt;
==End point description==&lt;br /&gt;
&lt;br /&gt;
===create===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will create a new invitation record with default reply_status: w. w stands for waiting.&lt;br /&gt;
REST VERB: POST&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success:&lt;br /&gt;
Status code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  &amp;quot;id&amp;quot;: 11,&lt;br /&gt;
  &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
  &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-20T21:33:29.580Z&amp;quot;,&lt;br /&gt;
  &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;oodd program3&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;jhon&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;jhon carmen&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example1@gmail.com&amp;quot;&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
    &amp;quot;fullname&amp;quot;: &amp;quot;katy shah&amp;quot;,&lt;br /&gt;
    &amp;quot;email&amp;quot;: &amp;quot;example2@gmail.com&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Failure:&lt;br /&gt;
Status code: 422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  error: @invitation.errors &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===index===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a list of all the invitations in the database.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&lt;br /&gt;
Request: NA&lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  },&lt;br /&gt;
  {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 3,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;rebecca&amp;quot;,&lt;br /&gt;
      &amp;quot;fullname&amp;quot;: &amp;quot;rebecca fiat&amp;quot;,&lt;br /&gt;
      &amp;quot;email&amp;quot;: &amp;quot;reb@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===show===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get a particular invite with the invite_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
success&lt;br /&gt;
status code: 200&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status code: 404&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;error&amp;quot;: &amp;quot;Couldn't find Invitation with 'id'=1021321&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===update===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: This route will modify the status of the invitation to be accepted or declined&lt;br /&gt;
REST VERB: PATCH&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;/&lt;br /&gt;
Request: &lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;reply_status&amp;quot;: [&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
    &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
    &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
    &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
        &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
        &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404/422&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===destroy===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Delete the invitation&lt;br /&gt;
REST VERB: DELETE&lt;br /&gt;
Path: /invitations/&amp;lt;invite_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status code: 204 :no_content&lt;br /&gt;
Response: NA&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404&lt;br /&gt;
Response&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitation.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===invitations_for_user_assignment===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Description: Get the invitations for the user with id: user_id for the given assignment with id: assignment_id.&lt;br /&gt;
REST VERB: GET&lt;br /&gt;
Path: /invitations/&amp;lt;user_id&amp;gt;/&amp;lt;assingment_id&amp;gt;&lt;br /&gt;
Request: NA&lt;br /&gt;
Response: &lt;br /&gt;
&lt;br /&gt;
Success&lt;br /&gt;
Status Code: 200 :ok&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
[&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;A&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-13T17:22:09.805Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-19T00:06:33.718Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;katy&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;katy kimson&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;kt@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;reply_status&amp;quot;: &amp;quot;W&amp;quot;,&lt;br /&gt;
        &amp;quot;created_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;updated_at&amp;quot;: &amp;quot;2023-04-18T15:52:44.543Z&amp;quot;,&lt;br /&gt;
        &amp;quot;assignment&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;program4&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;from_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;to_user&amp;quot;: {&lt;br /&gt;
            &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;john&amp;quot;,&lt;br /&gt;
            &amp;quot;fullname&amp;quot;: &amp;quot;john fella&amp;quot;,&lt;br /&gt;
            &amp;quot;email&amp;quot;: &amp;quot;john@gmail.com&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
Error&lt;br /&gt;
Status Code: 404 :not_found&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;error&amp;quot;: @invitations.errors&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== End point summary ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:40px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Method !! Endpoint !! Request Body !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 1 || create || POST &amp;lt;br/&amp;gt;/invitations/||assignment_id: INT, from_id: INT, to_id: INT, reply_status: CHAR ||Create a new invitation record with default reply_status: w, w stands for waiting.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || index || GET &amp;lt;br/&amp;gt;/invitations/ || ||Get a list of all the invitations.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || show || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get a particular invite with the invite_id.&lt;br /&gt;
|-&lt;br /&gt;
| 4 || update || PATCH /invitations/&amp;lt;invite_id&amp;gt;/ || &amp;quot;reply_status&amp;quot;=[&amp;quot;A&amp;quot;/&amp;quot;R&amp;quot;] || Modify the status of the invitation to be accepted or declined.&lt;br /&gt;
|-&lt;br /&gt;
| 5 || destroy || DELETE &amp;lt;br/&amp;gt; /invitations/&amp;lt;invite_id&amp;gt; || || Delete the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || invitations_for_user_assignment || GET &amp;lt;br/&amp;gt;/invitations/&amp;lt;assignment_id&amp;gt; || || Get the invitations for the user with id: user_id for the given assignment with id: assignment_id&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Testing Plan =&lt;br /&gt;
&lt;br /&gt;
We utilized RSpec as the testing framework for our system. We have used factoryBot along with Faker to create model objects for testing. The development process has followed Test Driven Development. The tests for the model and the controller are written in a comprehensive way.&lt;br /&gt;
&lt;br /&gt;
====Controller Tests====&lt;br /&gt;
&lt;br /&gt;
To run the controller tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/requests/api/v1/invitation_controller_spec.rb&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to list all Invitations&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with valid parameters&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with invalid 'to' user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with invalid 'from' user parameters&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to  create an invitation with invalid assignment parameters&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with invalid reply_status parameter&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to create an invitation with same to user and from user parameters'&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to show invitation with valid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to show invitation with invalid invitation id&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Test to accept invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Test to reject invite successfully&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Test to update invitation with invalid reply_status&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Test to update status with invalid invitation_id&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Test to delete invitation with valid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Test to delete invitation with invalid invite id&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Test to show all invitations for the user for an assignment&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Test to show invitation with invalid user and assignment&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Test to delete invitation with invalid invite idTest to Show invitation with user and invalid assignment&lt;br /&gt;
|-&lt;br /&gt;
| 19 ||Test to show invitation with invalid user and invalid assignment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_tests.png|900px]]&lt;br /&gt;
&lt;br /&gt;
====Model Tests====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To run the model tests:&lt;br /&gt;
&lt;br /&gt;
1. git clone &lt;br /&gt;
&lt;br /&gt;
2. cd reimplementation-back-end/&lt;br /&gt;
&lt;br /&gt;
3. bundle install&lt;br /&gt;
&lt;br /&gt;
4. bundle exec rspec spec/models/invitation_spec.rb&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left:30px&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Sr No !! Test Description &lt;br /&gt;
|-&lt;br /&gt;
| 1 || Test to create an invitation with valid parameters.&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Test to create an invitation with the same &amp;quot;to&amp;quot; and &amp;quot;from&amp;quot; user.&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Test to create an invitation with the invalid &amp;quot;to&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Test to create an invitation with the invalid &amp;quot;from&amp;quot; user parameter&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Test to create an invitation with a invalid assignment argument.&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Test to create an invitation with an invalid reply_status argument.&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Test to check is_invited? is a true case.&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Test to check is_invited? is a false case.&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Test to check if the default reply_status for a new invitation is WAITING('W').&lt;br /&gt;
|-&lt;br /&gt;
| 10|| Test to check if invitation_factory returns new invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 11|| Test to check if invitation email is sent properly.&lt;br /&gt;
|-&lt;br /&gt;
| 12|| Test to check if accept_invitation changes reply_status to 'A'.&lt;br /&gt;
|-&lt;br /&gt;
| 13|| Test to check if decline_invitation changes reply_status to 'R'.&lt;br /&gt;
|-&lt;br /&gt;
| 14|| Test to check if retract_invitation destroys the invitation.&lt;br /&gt;
|-&lt;br /&gt;
| 15|| Test to check if as_json formats invitation as required.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Rspec tests screenshot.&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:Dshah6_rspec_test2.png|900px]]&lt;br /&gt;
&lt;br /&gt;
== Swagger UI Screenshot ==&lt;br /&gt;
&lt;br /&gt;
Swagger is used to provide an easy to use API documentation for the users of the API. It also provides an easy to use interface to interact with the API in the browser itself. You can use the swagger page to test out our API by clicking on the &amp;quot;Try it out&amp;quot; button next to each route.&lt;br /&gt;
&lt;br /&gt;
path: /api-docs/&lt;br /&gt;
&lt;br /&gt;
[[File:Dshah6_swagger.png|900px]]&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/rohitgeddam/reimplementation-back-end/ Github Link]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/expertiza/reimplementation-back-end/pull/32 Github Pull Request]&lt;br /&gt;
&lt;br /&gt;
* [http://152.7.178.119:8080/  VCL Image Link]&lt;br /&gt;
&lt;br /&gt;
* [http://rspec.info/documentation/3.8/rspec-core/ Rspec Documentation]&lt;br /&gt;
&lt;br /&gt;
=Team Members=&lt;br /&gt;
&lt;br /&gt;
* Saigirishwar Rohit Geddam&lt;br /&gt;
* Keerthana Telaprolu&lt;br /&gt;
* Dhrumil Shah&lt;br /&gt;
&lt;br /&gt;
=Mentor=&lt;br /&gt;
Ankur Mundra&lt;/div&gt;</summary>
		<author><name>Sgeddam2</name></author>
	</entry>
</feed>