Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[BE]APIs to save invoices #256

Merged
merged 6 commits into from
Apr 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions app/controllers/internal_api/v1/invoices_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,37 @@ def index
}
}
end

def create
authorize Invoice
render :create, locals: {
invoice: Invoice.create!(invoice_params),
shivamsinghchahar marked this conversation as resolved.
Show resolved Hide resolved
client: load_client(invoice_params[:client_id])
}
end

def update
authorize invoice
invoice.update!(invoice_params)
render :update, locals: {
invoice:,
client: load_client(invoice[:client_id])
}
end

private

def load_client(client_id)
Client.find(client_id)
end

def invoice
@_invoice ||= Invoice.find(params[:id])
end

def invoice_params
params.require(:invoice).permit(
policy(Invoice).permitted_attributes
)
end
end
17 changes: 17 additions & 0 deletions app/policies/invoice_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,24 @@ def index?
user_owner_or_admin?
end

def create?
user_owner_or_admin?
end

def update?
user_owner_or_admin?
end

def show?
user_owner_or_admin?
end

def permitted_attributes
[
:issue_date, :due_date,
:invoice_number, :reference, :amount,
:outstanding_amount, :tax, :amount_paid,
:amount_due, :discount, :client_id
]
end
end
20 changes: 20 additions & 0 deletions app/views/internal_api/v1/invoices/_invoice.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

json.key_format! camelize: :lower
json.deep_format_keys!

json.id invoice.id
json.invoice_number invoice.invoice_number
json.issue_date invoice.issue_date
json.due_date invoice.due_date
json.reference invoice.reference
json.amount invoice.amount
json.outstanding_amount invoice.outstanding_amount
json.amount_paid invoice.amount_paid
json.amount_due invoice.amount_due
json.discount invoice.discount
json.tax invoice.tax
json.status invoice.status
json.client do
json.name client.name
end
3 changes: 3 additions & 0 deletions app/views/internal_api/v1/invoices/create.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

json.partial! "invoice", locals: { invoice:, client: }
3 changes: 3 additions & 0 deletions app/views/internal_api/v1/invoices/update.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

json.partial! "invoice", locals: { invoice:, client: }
2 changes: 1 addition & 1 deletion config/routes/internal_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
resources :timesheet_entry, only: [:index, :create, :update, :destroy]
resources :reports, only: [:index]
resources :workspaces, only: [:update]
resources :invoices, only: [:index]
resources :invoices, only: [:index, :create, :update]
resources :generate_invoice, only: [:index, :show]
end
end
70 changes: 70 additions & 0 deletions spec/requests/internal_api/v1/invoices/create_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe "InternalApi::V1::Invoices#create", type: :request do
let(:company) do
create(:company, clients: create_list(:client_with_invoices, 5))
end

let(:user) { create(:user, current_workspace_id: company.id) }

context "when user is admin" do
before do
create(:company_user, company:, user:)
user.add_role :admin, company
sign_in user
end

describe "invoice creation" do
it "creates invoice successfully" do
invoice = attributes_for(
:invoice,
client: company.clients.first,
client_id: company.clients.first.id,
status: :draft)
send_request :post, internal_api_v1_invoices_path(invoice:)
expect(response).to have_http_status(:ok)
expected_attrs = ["amount", "amountDue", "amountPaid",
"client", "discount", "dueDate", "id",
"invoiceNumber", "issueDate", "outstandingAmount",
"reference", "status", "tax"]
expect(json_response.keys.sort).to match(expected_attrs)
end

it "throws 422 if client doesn't exist" do
send_request :post, internal_api_v1_invoices_path(
invoice: {
client_id: 100000,
invoice_number: "INV0001",
reference: "bar",
issue_date: "2022-01-01",
due_date: "2022-01-31"
})
expect(response).to have_http_status(:unprocessable_entity)
expect(json_response["errors"]["client"].first).to eq("must exist")
end
end
end

context "when user is employee" do
before do
create(:company_user, company:, user:)
user.add_role :employee, company
sign_in user
send_request :post, internal_api_v1_invoices_path
end

it "is not be permitted to generate an invoice" do
expect(response).to have_http_status(:forbidden)
end
end

context "when unauthenticated" do
it "is not be permitted to generate an invoice" do
send_request :post, internal_api_v1_invoices_path
expect(response).to have_http_status(:unauthorized)
expect(json_response["error"]).to eq("You need to sign in or sign up before continuing.")
end
end
end
65 changes: 65 additions & 0 deletions spec/requests/internal_api/v1/invoices/update_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe "InternalApi::V1::Invoices#update", type: :request do
let(:company) do
create(:company, clients: create_list(:client_with_invoices, 5))
end

let(:user) { create(:user, current_workspace_id: company.id) }

context "when user is admin" do
before do
create(:company_user, company:, user:)
user.add_role :admin, company
sign_in user
end

describe "invoice updation" do
it "updates invoice successfully" do
send_request :patch, internal_api_v1_invoice_path(
id: company.clients.first.invoices.first.id, params: {
invoice: {
reference: "foo"
}
})
expect(response).to have_http_status(:ok)
expect(json_response["reference"]).to eq("foo")
end

it "throws 422 if client doesn't exist" do
send_request :patch, internal_api_v1_invoice_path(
id: company.clients.first.invoices.first.id, params: {
invoice: {
client_id: 100000,
reference: "foo"
}
})
expect(response).to have_http_status(:unprocessable_entity)
expect(json_response["errors"]["client"].first).to eq("must exist")
end
end
end

context "when user is employee" do
before do
create(:company_user, company:, user:)
user.add_role :employee, company
sign_in user
send_request :patch, internal_api_v1_invoice_path(id: company.clients.first.invoices.first.id)
end

it "is not be permitted to update an invoice" do
expect(response).to have_http_status(:forbidden)
end
end

context "when unauthenticated" do
it "is not be permitted to update an invoice" do
send_request :patch, internal_api_v1_invoice_path(id: 1)
expect(response).to have_http_status(:unauthorized)
expect(json_response["error"]).to eq("You need to sign in or sign up before continuing.")
end
end
end