mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-11 03:40:20 +00:00
Add api endpoing to create customer transactions
Plus specs and documentation
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V1
|
||||
class CustomerAccountTransactionController < Api::V1::BaseController
|
||||
def create
|
||||
authorize! :create, CustomerAccountTransaction
|
||||
|
||||
# We only allow using the api customer credit payment method
|
||||
default_params = { currency: CurrentConfig.get(:currency), payment_method_id: }
|
||||
transaction = CustomerAccountTransaction.new(
|
||||
default_params.merge(customer_account_transaction_params)
|
||||
)
|
||||
|
||||
if transaction.save
|
||||
render json: Api::V1::CustomerAccountTransactionSerializer.new(transaction),
|
||||
status: :created
|
||||
else
|
||||
invalid_resource! transaction
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def customer_account_transaction_params
|
||||
params.require(:customer_account_transaction).permit(:customer_id, :amount, :description)
|
||||
end
|
||||
|
||||
def payment_method_id
|
||||
Spree::PaymentMethod.internal.find_by(
|
||||
name: Rails.application.config.api_payment_method[:name]
|
||||
)&.id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
31
app/json_schemas/customer_account_transaction_schema.rb
Normal file
31
app/json_schemas/customer_account_transaction_schema.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CustomerAccountTransactionSchema < JsonApiSchema
|
||||
def self.object_name
|
||||
"customer_account_transaction"
|
||||
end
|
||||
|
||||
def self.attributes
|
||||
{
|
||||
id: { type: :integer, example: 1 },
|
||||
customer_id: { type: :integer, example: 10 },
|
||||
amount: { type: :decimal, example: 10.50 },
|
||||
currency: { type: :string, example: "AUD" },
|
||||
payment_method_id: { type: :integer, example: 100 },
|
||||
description: { type: :string, nullable: true, example: "Payment processed by POS" },
|
||||
balance: { type: :decimal, example: 10.50 },
|
||||
}
|
||||
end
|
||||
|
||||
def self.required_attributes
|
||||
[:customer_id, :amount]
|
||||
end
|
||||
|
||||
def self.writable_attributes
|
||||
attributes.except(:id, :balance, :payment_method_id, :currency)
|
||||
end
|
||||
|
||||
def self.relationships
|
||||
[:customer, :payment_method]
|
||||
end
|
||||
end
|
||||
@@ -61,6 +61,7 @@ module Spree
|
||||
add_manage_line_items_abilities user
|
||||
end
|
||||
add_relationship_management_abilities user if can_manage_relationships? user
|
||||
add_customer_payment_abilities user if can_manage_enterprises? user
|
||||
end
|
||||
|
||||
# New users have no enterprises.
|
||||
@@ -457,5 +458,9 @@ module Spree
|
||||
user.enterprises.include?(enterprise_relationship.child)
|
||||
end
|
||||
end
|
||||
|
||||
def add_customer_payment_abilities(_user)
|
||||
can [:create], CustomerAccountTransaction
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
module V1
|
||||
class CustomerAccountTransactionSerializer < Api::V1::BaseSerializer
|
||||
attributes :id, :customer_id, :payment_method_id, :amount, :currency, :description, :balance
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -92,6 +92,8 @@ Openfoodnetwork::Application.routes.draw do
|
||||
resources :enterprises do
|
||||
resources :customers, only: :index
|
||||
end
|
||||
|
||||
resources :customer_account_transaction, only: [:create]
|
||||
end
|
||||
|
||||
match '*path', to: redirect(path: "/api/v0/%{path}"), via: :all,
|
||||
|
||||
112
spec/requests/api/v1/customer_account_transaction_spec.rb
Normal file
112
spec/requests/api/v1/customer_account_transaction_spec.rb
Normal file
@@ -0,0 +1,112 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "swagger_helper"
|
||||
|
||||
RSpec.describe "CustomerAccountTransactions", swagger_doc: "v1.yaml", feature: :api_v1 do
|
||||
let!(:enterprise) { create(:enterprise) }
|
||||
let(:payment_method) {
|
||||
create(
|
||||
:payment_method,
|
||||
name: CustomerAccountTransaction::DEFAULT_PAYMENT_METHOD_NAME,
|
||||
distributors: [enterprise]
|
||||
)
|
||||
}
|
||||
let(:customer) { create(:customer) }
|
||||
|
||||
before do
|
||||
login_as enterprise.owner
|
||||
end
|
||||
|
||||
path "/api/v1/customer_account_transaction" do
|
||||
post "Create customer transaction" do
|
||||
tags "Customer account transaction"
|
||||
consumes "application/json"
|
||||
produces "application/json"
|
||||
|
||||
parameter name: :customer_account_transaction, in: :body, schema: {
|
||||
type: :object,
|
||||
properties: CustomerAccountTransactionSchema.writable_attributes,
|
||||
required: CustomerAccountTransactionSchema.required_attributes
|
||||
}
|
||||
|
||||
response "201", "Customer transaction created" do
|
||||
let(:customer_account_transaction) do
|
||||
{
|
||||
customer_id: customer.id.to_s,
|
||||
amount: "10.25",
|
||||
description: "Payment processed by POS"
|
||||
}
|
||||
end
|
||||
schema '$ref': "#/components/schemas/customer_account_transaction"
|
||||
|
||||
run_test! do
|
||||
expect(json_response[:data][:attributes]).to include(
|
||||
customer_id: customer.id,
|
||||
payment_method_id: payment_method.id,
|
||||
amount: "10.25",
|
||||
currency: "AUD",
|
||||
description: "Payment processed by POS",
|
||||
balance: "10.25",
|
||||
)
|
||||
|
||||
transaction = CustomerAccountTransaction.find(json_response[:data][:attributes][:id])
|
||||
expect(transaction).not_to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
response "422", "Unpermitted parameter" do
|
||||
let(:customer_account_transaction) do
|
||||
{
|
||||
id: 101,
|
||||
customer_id: customer.id.to_s,
|
||||
amount: "10.25",
|
||||
}
|
||||
end
|
||||
schema '$ref': "#/components/schemas/error_response"
|
||||
|
||||
run_test! do
|
||||
expect(json_response[:errors][0][:detail]).to eq(
|
||||
"Parameters not allowed in this request: id"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
response "422", "Unprocessable entity" do
|
||||
let(:customer_account_transaction) { {} }
|
||||
schema '$ref': "#/components/schemas/error_response"
|
||||
|
||||
run_test! do
|
||||
expect(json_response[:errors][0][:detail]).to eq(
|
||||
"A required parameter is missing or empty: customer_account_transaction"
|
||||
)
|
||||
expect(json_response[:meta]).to eq nil
|
||||
end
|
||||
end
|
||||
|
||||
response "422", "Invalid resource" do
|
||||
let(:customer_account_transaction) { { amount: "10.25" } }
|
||||
schema '$ref': "#/components/schemas/error_response"
|
||||
|
||||
run_test! do
|
||||
expect(json_response[:errors][0][:detail]).to eq(
|
||||
"Invalid resource. Please fix errors and try again."
|
||||
)
|
||||
expect(json_response[:meta][:validation_errors]).to eq ["Customer must exist"]
|
||||
end
|
||||
end
|
||||
|
||||
response "401", "Unauthorized" do
|
||||
before { login_as nil }
|
||||
|
||||
let(:customer_account_transaction) do
|
||||
{
|
||||
customer_id: customer.id.to_s,
|
||||
amount: "10.25",
|
||||
}
|
||||
end
|
||||
|
||||
run_test!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -27,7 +27,9 @@ RSpec.configure do |config|
|
||||
error_response: ErrorsSchema.schema,
|
||||
# only customer#show is with extra_fields: {name: :balance, required: true}
|
||||
customer: CustomerSchema.schema(require_all: true),
|
||||
customers_collection: CustomerSchema.collection(require_all: true, extra_fields: :balance)
|
||||
customers_collection: CustomerSchema.collection(require_all: true,
|
||||
extra_fields: :balance),
|
||||
customer_account_transaction: CustomerAccountTransactionSchema.schema(require_all: true)
|
||||
},
|
||||
securitySchemes: {
|
||||
api_key_header: {
|
||||
|
||||
136
swagger/v1.yaml
136
swagger/v1.yaml
@@ -77,7 +77,7 @@ components:
|
||||
billing_address:
|
||||
type: object
|
||||
nullable: true
|
||||
example:
|
||||
example:
|
||||
shipping_address:
|
||||
type: object
|
||||
nullable: true
|
||||
@@ -190,7 +190,7 @@ components:
|
||||
billing_address:
|
||||
type: object
|
||||
nullable: true
|
||||
example:
|
||||
example:
|
||||
shipping_address:
|
||||
type: object
|
||||
nullable: true
|
||||
@@ -283,6 +283,92 @@ components:
|
||||
- data
|
||||
- meta
|
||||
- links
|
||||
customer_account_transaction:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
example: '1'
|
||||
type:
|
||||
type: string
|
||||
example: customer_account_transaction
|
||||
attributes:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
example: 1
|
||||
customer_id:
|
||||
type: integer
|
||||
example: 10
|
||||
amount:
|
||||
type: decimal
|
||||
example: 10.5
|
||||
currency:
|
||||
type: string
|
||||
example: AUD
|
||||
payment_method_id:
|
||||
type: integer
|
||||
example: 100
|
||||
description:
|
||||
type: string
|
||||
nullable: true
|
||||
example: Payment processed by POS
|
||||
balance:
|
||||
type: decimal
|
||||
example: 10.5
|
||||
required:
|
||||
- id
|
||||
- customer_id
|
||||
- amount
|
||||
- currency
|
||||
- payment_method_id
|
||||
- description
|
||||
- balance
|
||||
relationships:
|
||||
type: object
|
||||
properties:
|
||||
customer:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
example: customer
|
||||
links:
|
||||
type: object
|
||||
properties:
|
||||
related:
|
||||
type: string
|
||||
payment_method:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
example: payment_method
|
||||
links:
|
||||
type: object
|
||||
properties:
|
||||
related:
|
||||
type: string
|
||||
meta:
|
||||
type: object
|
||||
links:
|
||||
type: object
|
||||
required:
|
||||
- data
|
||||
securitySchemes:
|
||||
api_key_header:
|
||||
type: apiKey
|
||||
@@ -300,6 +386,46 @@ components:
|
||||
in: cookie
|
||||
description: Authenticates using the current user's session if logged in
|
||||
paths:
|
||||
"/api/v1/customer_account_transaction":
|
||||
post:
|
||||
summary: Create customer transaction
|
||||
tags:
|
||||
- Customer account transaction
|
||||
parameters: []
|
||||
responses:
|
||||
'201':
|
||||
description: Customer transaction created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/customer_account_transaction"
|
||||
'422':
|
||||
description: Invalid resource
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/error_response"
|
||||
'401':
|
||||
description: Unauthorized
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
customer_id:
|
||||
type: integer
|
||||
example: 10
|
||||
amount:
|
||||
type: decimal
|
||||
example: 10.5
|
||||
description:
|
||||
type: string
|
||||
nullable: true
|
||||
example: Payment processed by POS
|
||||
required:
|
||||
- customer_id
|
||||
- amount
|
||||
"/api/v1/customers":
|
||||
get:
|
||||
summary: List customers
|
||||
@@ -375,7 +501,7 @@ paths:
|
||||
billing_address:
|
||||
type: object
|
||||
nullable: true
|
||||
example:
|
||||
example:
|
||||
shipping_address:
|
||||
type: object
|
||||
nullable: true
|
||||
@@ -468,7 +594,7 @@ paths:
|
||||
billing_address:
|
||||
type: object
|
||||
nullable: true
|
||||
example:
|
||||
example:
|
||||
shipping_address:
|
||||
type: object
|
||||
nullable: true
|
||||
@@ -598,7 +724,7 @@ paths:
|
||||
billing_address:
|
||||
type: object
|
||||
nullable: true
|
||||
example:
|
||||
example:
|
||||
shipping_address:
|
||||
type: object
|
||||
nullable: true
|
||||
|
||||
Reference in New Issue
Block a user