Skip to content

Commit

Permalink
Merge pull request #18 from Boulevard/sales-receipts
Browse files Browse the repository at this point in the history
Add salesreceipt create and void support
  • Loading branch information
lnikkila authored Sep 21, 2017
2 parents 90d082b + 375ca73 commit 7a09dc0
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 1 deletion.
52 changes: 52 additions & 0 deletions lib/exquickbooks/api/sales_receipt.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
defmodule ExQuickBooks.API.SalesReceipt do
@moduledoc """
Functions for interacting with the SalesReceipt API.
This module directly implements operations from the official API:
<https://developer.intuit.com/docs/api/accounting/salesreceipt>
"""

use ExQuickBooks.Endpoint, base_url: ExQuickBooks.accounting_api
use ExQuickBooks.Endpoint.JSON

alias ExQuickBooks.OAuth.AccessToken

@doc """
Creates an Sales Receipt.
A SalesReceipt object must have at least one line that describes an item
and an amount.
"""
@spec create_sales_receipt(AccessToken.t, json_map) ::
{:ok, json_map} | {:error, any}
def create_sales_receipt(token, sales_receipt) do
request(:post, "company/#{token.realm_id}/salesreceipt", sales_receipt)
|> sign_request(token)
|> send_json_request
end

@doc """
Retrieves a Sales Receipt.
"""
@spec read_sales_receipt(AccessToken.t, String.t) ::
{:ok, json_map} | {:error, any}
def read_sales_receipt(token, sales_receipt_id) do
request(:get, "company/#{token.realm_id}/salesreceipt/#{sales_receipt_id}")
|> sign_request(token)
|> send_json_request
end

@doc """
Void a Sales Receipt. Must include Sparse, Id, and SyncToken as
sales_receipt attributes.
"""
@spec void_sales_receipt(AccessToken.t, json_map) ::
{:ok, json_map} | {:error, any}
def void_sales_receipt(token, sales_receipt) do
request(:post, "company/#{token.realm_id}/salesreceipt", sales_receipt, nil, params: [
{"include", "void"}
])
|> sign_request(token)
|> send_json_request
end
end
53 changes: 53 additions & 0 deletions test/exquickbooks/api/sales_receipt_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
defmodule ExQuickBooks.API.SalesReceiptTest do
use ExUnit.Case, async: false
use ExQuickBooks.APICase

alias ExQuickBooks.API.SalesReceipt
alias ExQuickBooks.OAuth.AccessToken

doctest SalesReceipt

@token %AccessToken{
token: "token",
token_secret: "secret",
realm_id: "realm_id"
}

test "create_sales_receipt/3 creates an sales_receipt" do
load_response("sales_receipt/create_sales_receipt.json") |> send_response

assert {:ok, %{"SalesReceipt" => _}} =
SalesReceipt.create_sales_receipt(@token, %{foo: true})

assert %{body: body} = take_request()
assert String.contains?(to_string(body), "foo")
end

test "create_sales_receipt/3 recovers from an error" do
load_response("sales_receipt/create_sales_receipt_error.json")
|> Map.put(:status_code, 400)
|> send_response

assert {:error, %{"Fault" => _}} =
SalesReceipt.create_sales_receipt(@token, %{foo: true})
end

test "void_sales_receipt/3 voids and retrieves an sales_receipt" do
load_response("sales_receipt/void_sales_receipt.json") |> send_response

assert {:ok, %{"SalesReceipt" => _}} =
SalesReceipt.void_sales_receipt(@token, %{foo: true})

assert %{body: body} = take_request()
assert String.contains?(to_string(body), "foo")
end

test "void_sales_receipt/3 recovers from an error" do
load_response("sales_receipt/void_sales_receipt_error.json")
|> Map.put(:status_code, 400)
|> send_response

assert {:error, %{"Fault" => _}} =
SalesReceipt.void_sales_receipt(@token, %{foo: true})
end
end
6 changes: 5 additions & 1 deletion test/exquickbooks_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,17 @@ defmodule ExQuickBooksTest do
Application.delete_env(:exquickbooks, key)
end

defp keyword_list_equal?(env1, env2) do
List.keysort(env1, 1) == List.keysort(env2, 1)
end

defp restore_env(old_env) do
new_env = get_all_env()

for {k, _} <- new_env, do: delete_env(k)
for {k, v} <- old_env, do: put_env(k, v)

get_all_env() == old_env || raise """
keyword_list_equal?(get_all_env(), old_env) || raise """
Could not restore the application's environment. Check that you're not
modifying it simultaneously in other tests. Those tests should specify
`async: false`.
Expand Down
57 changes: 57 additions & 0 deletions test/fixtures/sales_receipt/create_sales_receipt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"time": "2017-09-20T18:32:11.363-07:00",
"SalesReceipt": {
"sparse": false,
"domain": "QBO",
"TxnDate": "2017-09-20",
"TotalAmt": 0,
"SyncToken": "0",
"PrintStatus": "NeedToPrint",
"MetaData": {
"LastUpdatedTime": "2017-09-20T18:32:11-07:00",
"CreateTime": "2017-09-20T18:32:11-07:00"
},
"Line": [
{
"SalesItemLineDetail": {
"UnitPrice": 0,
"TaxCodeRef": {
"value": "NON"
},
"Qty": 1,
"ItemRef": {
"value": "3",
"name": "Oribe:Shampoo:Test Product"
}
},
"LineNum": 1,
"Id": "1",
"DetailType": "SalesItemLineDetail",
"Amount": 0
},
{
"SubTotalLineDetail": {

},
"DetailType": "SubTotalLineDetail",
"Amount": 0
}
],
"Id": "6",
"EmailStatus": "NotSet",
"DocNumber": "1005",
"DepositToAccountRef": {
"value": "4",
"name": "Undeposited Funds"
},
"CustomField": [

],
"CurrencyRef": {
"value": "USD",
"name": "United States Dollar"
},
"Balance": 0,
"ApplyTaxAfterDiscount": false
}
}
14 changes: 14 additions & 0 deletions test/fixtures/sales_receipt/create_sales_receipt_error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"time": "2017-09-20T18:40:29.968-07:00",
"Fault": {
"type": "ValidationFault",
"Error": [
{
"element": "Line.DetailType",
"code": "2020",
"Message": "Required param missing, need to supply the required value for the API",
"Detail": "Required parameter Line.DetailType is missing in the request"
}
]
}
}
58 changes: 58 additions & 0 deletions test/fixtures/sales_receipt/void_sales_receipt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"time": "2017-09-20T18:33:39.066-07:00",
"SalesReceipt": {
"sparse": false,
"domain": "QBO",
"TxnDate": "2017-09-20",
"TotalAmt": 0,
"SyncToken": "1",
"PrivateNote": "Voided",
"PrintStatus": "NeedToPrint",
"MetaData": {
"LastUpdatedTime": "2017-09-20T18:33:39-07:00",
"CreateTime": "2017-09-20T18:32:11-07:00"
},
"Line": [
{
"SalesItemLineDetail": {
"UnitPrice": 0,
"TaxCodeRef": {
"value": "NON"
},
"Qty": 0,
"ItemRef": {
"value": "3",
"name": "Oribe:Shampoo:Test Product"
}
},
"LineNum": 1,
"Id": "1",
"DetailType": "SalesItemLineDetail",
"Amount": 0
},
{
"SubTotalLineDetail": {

},
"DetailType": "SubTotalLineDetail",
"Amount": 0
}
],
"Id": "6",
"EmailStatus": "NotSet",
"DocNumber": "1005",
"DepositToAccountRef": {
"value": "4",
"name": "Undeposited Funds"
},
"CustomField": [

],
"CurrencyRef": {
"value": "USD",
"name": "United States Dollar"
},
"Balance": 0,
"ApplyTaxAfterDiscount": false
}
}
14 changes: 14 additions & 0 deletions test/fixtures/sales_receipt/void_sales_receipt_error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"time": "2017-09-20T18:43:12.415-07:00",
"Fault": {
"type": "ValidationFault",
"Error": [
{
"element": "",
"code": "5010",
"Message": "Stale Object Error",
"Detail": "Stale Object Error : You and John Doe were working on this at the same time. John Doe finished before you did, so your work was not saved."
}
]
}
}

0 comments on commit 7a09dc0

Please sign in to comment.