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

feat: standardize validate opts query params, accept on GET/POST validate #1413

Merged
merged 1 commit into from
Apr 26, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 5 additions & 3 deletions docs/create-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,20 @@ Example: `POST /files/create?requireABAOrigin=true&bypassDestination=true`
| `allowInvalidCheckDigit` | `AllowInvalidCheckDigit` |
| `allowMissingFileControl` | `AllowMissingFileControl` |
| `allowMissingFileHeader` | `AllowMissingFileHeader` |
| `allowUnorderedBatchNumbers` | `AllowUnorderedBatchNumbers` |
| `allowZeroBatches` | `AllowZeroBatches` |
| `bypassCompanyIdentificationMatch` | `BypassCompanyIdentificationMatch` |
| `bypassDestination` | `BypassDestinationValidation` |
| `bypassOrigin` | `BypassOriginValidation` |
| `bypassDestinationValidation` | `BypassDestinationValidation` |
| `bypassOriginValidation` | `BypassOriginValidation` |
| `customReturnCodes` | `CustomReturnCodes` |
| `customTraceNumbers` | `CustomTraceNumbers` |
| `preserveSpaces` | `PreserveSpaces` |
| `requireABAOrigin` | `RequireABAOrigin` |
| `skipAll` | `SkipAll` |
| `unequalAddendaCounts` | `UnequalAddendaCounts` |
| `unequalServiceClassCode` | `UnequalServiceClassCode` |
| `unorderedBatchNumbers` | `AllowUnorderedBatchNumbers` |

> Note: `bypassDestination`, `bypassOrigin`, and `unorderedBatchNumbers` are deprecated query parameters replace by identical named parameters.

## Upload a raw ACH file

Expand Down
99 changes: 99 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,23 @@ paths:
description: Optional parameter to configure ImmediateOrigin validation
schema:
type: boolean
deprecated: true
- name: bypassOriginValidation
in: query
description: Optional parameter to configure ImmediateOrigin validation
schema:
type: boolean
- name: bypassDestination
in: query
description: Optional parameter to configure ImmediateDestination validation
schema:
type: boolean
deprecated: true
- name: bypassDestinationValidation
in: query
description: Optional parameter to configure ImmediateDestination validation
schema:
type: boolean
- name: customTraceNumbers
in: query
description: Optional parameter to configure ImmediateDestination validation
Expand Down Expand Up @@ -134,6 +146,12 @@ paths:
description: Allow a file to be read with unordered batch numbers.
schema:
type: boolean
deprecated: true
- name: allowUnorderedBatchNumbers
in: query
description: Allow a file to be read with unordered batch numbers.
schema:
type: boolean
- name: allowInvalidCheckDigit
in: query
description: Allow the CheckDigit field in EntryDetail to differ from the expected calculation
Expand Down Expand Up @@ -304,6 +322,87 @@ paths:
schema:
$ref: '#/components/schemas/RawFile'
/files/{fileID}/validate:
parameters:
- name: skipAll
in: query
description: Optional parameter to disable all validation checks for a File
schema:
type: boolean
- name: requireABAOrigin
in: query
description: Optional parameter to configure ImmediateOrigin validation
schema:
type: boolean
- name: bypassOriginValidation
in: query
description: Optional parameter to configure ImmediateOrigin validation
schema:
type: boolean
- name: bypassDestinationValidation
in: query
description: Optional parameter to configure ImmediateDestination validation
schema:
type: boolean
- name: customTraceNumbers
in: query
description: Optional parameter to configure ImmediateDestination validation
schema:
type: boolean
- name: allowZeroBatches
in: query
description: Optional parameter to configure ImmediateDestination validation
schema:
type: boolean
- name: allowMissingFileHeader
in: query
description: Optional parameter to configure ImmediateDestination validation
schema:
type: boolean
- name: allowMissingFileControl
in: query
description: Optional parameter to configure ImmediateDestination validation
schema:
type: boolean
- name: bypassCompanyIdentificationMatch
in: query
description: Optional parameter to configure ImmediateDestination validation
schema:
type: boolean
- name: customReturnCodes
in: query
description: Optional parameter to configure ImmediateDestination validation
schema:
type: boolean
- name: unequalServiceClassCode
in: query
description: Optional parameter to configure ImmediateDestination validation
schema:
type: boolean
- name: allowUnorderedBatchNumbers
in: query
description: Allow a file to be read with unordered batch numbers.
schema:
type: boolean
- name: allowInvalidCheckDigit
in: query
description: Allow the CheckDigit field in EntryDetail to differ from the expected calculation
schema:
type: boolean
- name: unequalAddendaCounts
in: query
description: Optional parameter to configure UnequalAddendaCounts validation
schema:
type: boolean
- name: preserveSpaces
in: query
description: Optional parameter to save all padding spaces
schema:
type: boolean
- name: allowInvalidAmounts
in: query
description: Optional parameter to save all padding spaces
schema:
type: boolean
get:
tags: ['ACH Files']
summary: Validate File
Expand Down
117 changes: 15 additions & 102 deletions server/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"strings"

"github.com/moov-io/ach"
Expand Down Expand Up @@ -117,104 +116,17 @@ func createFileEndpoint(s Service, r Repository, logger log.Logger) endpoint.End
func decodeCreateFileRequest(_ context.Context, request *http.Request) (interface{}, error) {
var r io.Reader
req := createFileRequest{
File: ach.NewFile(),
requestID: moovhttp.GetRequestID(request),
validateOpts: &ach.ValidateOpts{},
}

const (
skipAll = "skipAll"
requireABAOrigin = "requireABAOrigin"
bypassOrigin = "bypassOrigin"
bypassDestination = "bypassDestination"
customTraceNumbers = "customTraceNumbers"
allowZeroBatches = "allowZeroBatches"
allowMissingFileHeader = "allowMissingFileHeader"
allowMissingFileControl = "allowMissingFileControl"
bypassCompanyIdentificationMatch = "bypassCompanyIdentificationMatch"
customReturnCodes = "customReturnCodes"
unequalServiceClassCode = "unequalServiceClassCode"
unorderedBatchNumbers = "unorderedBatchNumbers"
allowInvalidCheckDigit = "allowInvalidCheckDigit"
unequalAddendaCounts = "unequalAddendaCounts"
preserveSpaces = "preserveSpaces"
allowInvalidAmounts = "allowInvalidAmounts"
)

validationNames := []string{
skipAll,
requireABAOrigin,
bypassOrigin,
bypassDestination,
customTraceNumbers,
allowZeroBatches,
allowMissingFileHeader,
allowMissingFileControl,
bypassCompanyIdentificationMatch,
customReturnCodes,
unequalServiceClassCode,
unorderedBatchNumbers,
allowInvalidCheckDigit,
unequalAddendaCounts,
preserveSpaces,
allowInvalidAmounts,
}

for _, name := range validationNames {
q := request.URL.Query()
if q == nil {
continue
}
input := q.Get(name)
if input == "" {
continue
}

ok, err := strconv.ParseBool(input)
if err != nil {
return nil, fmt.Errorf("invalid bool: %v", err)
}
if !ok {
continue
}

switch name {
case skipAll:
req.validateOpts.SkipAll = true
case requireABAOrigin:
req.validateOpts.RequireABAOrigin = true
case bypassOrigin:
req.validateOpts.BypassOriginValidation = true
case bypassDestination:
req.validateOpts.BypassDestinationValidation = true
case customTraceNumbers:
req.validateOpts.CustomTraceNumbers = true
case allowZeroBatches:
req.validateOpts.AllowZeroBatches = true
case allowMissingFileHeader:
req.validateOpts.AllowMissingFileHeader = true
case allowMissingFileControl:
req.validateOpts.AllowMissingFileControl = true
case bypassCompanyIdentificationMatch:
req.validateOpts.BypassCompanyIdentificationMatch = true
case customReturnCodes:
req.validateOpts.CustomReturnCodes = true
case unequalServiceClassCode:
req.validateOpts.UnequalServiceClassCode = true
case unorderedBatchNumbers:
req.validateOpts.AllowUnorderedBatchNumbers = true
case allowInvalidCheckDigit:
req.validateOpts.AllowInvalidCheckDigit = true
case unequalAddendaCounts:
req.validateOpts.UnequalAddendaCounts = true
case preserveSpaces:
req.validateOpts.PreserveSpaces = true
case allowInvalidAmounts:
req.validateOpts.AllowInvalidAmounts = true
}
}

bs, err := io.ReadAll(request.Body)
File: ach.NewFile(),
requestID: moovhttp.GetRequestID(request),
}

body, validateOpts, err := readValidateOpts(request)
if err != nil {
return nil, err
}
req.validateOpts = validateOpts

bs, err := io.ReadAll(body)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -538,10 +450,11 @@ func decodeValidateFileRequest(_ context.Context, r *http.Request) (interface{},
requestID: moovhttp.GetRequestID(r),
}

var opts ach.ValidateOpts
if err := json.NewDecoder(r.Body).Decode(&opts); err == nil {
req.opts = &opts
_, validateOpts, err := readValidateOpts(r)
if err != nil {
return nil, err
}
req.opts = validateOpts

return req, nil
}
Expand Down
13 changes: 13 additions & 0 deletions server/test/unordered_batches/unordered_batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@ func TestUnorderedBatches(t *testing.T) {
req = httptest.NewRequest("POST", fmt.Sprintf("/files/%s/validate", response.ID), &buf)
server.Handler.ServeHTTP(w, req)
w.Flush()
require.Equal(t, http.StatusOK, w.Code)

// Try POST /validate with ?unorderedBatchNumbers
w = httptest.NewRecorder()
req = httptest.NewRequest("POST", fmt.Sprintf("/files/%s/validate?unorderedBatchNumbers=true", response.ID), nil)
server.Handler.ServeHTTP(w, req)
w.Flush()
require.Equal(t, http.StatusOK, w.Code)

// Try POST /validate with ?allowUnorderedBatchNumbers
w = httptest.NewRecorder()
req = httptest.NewRequest("POST", fmt.Sprintf("/files/%s/validate?allowUnorderedBatchNumbers=true", response.ID), nil)
server.Handler.ServeHTTP(w, req)
w.Flush()
require.Equal(t, http.StatusOK, w.Code)
}