Skip to content
This repository was archived by the owner on Jun 26, 2025. It is now read-only.

Add header record using Fixy and DryRB Validation gems#5

Merged
SmileAndCompile merged 22 commits intomainfrom
zi/ZEP-1944-fixy-gem
May 24, 2022
Merged

Add header record using Fixy and DryRB Validation gems#5
SmileAndCompile merged 22 commits intomainfrom
zi/ZEP-1944-fixy-gem

Conversation

@zachingle
Copy link
Contributor

@zachingle zachingle commented May 20, 2022

This PR uses both the fixy and dry-validation gems to generate and validate the header record. dry-validation is used on the header record's initialisation to validate the data coming into the object. We then use fixy to format the data to ASB specs.

Specs for the MT9 file format can be found on page 42 and 62 of the ASB File Formats Technical Guide or the MT9 File Formats found in our GDrive

A macro is used for the account number so the rules can be shared with the detail record.

Seems like there is an issue for fixy subclass records not properly inheriting the line ending and record fields: OmarSkalli/fixy#25 but I don't think this is a big blocker. It'll just mean duplicating the set_line_ending line across the records.

attr_reader :file_type, :account_number, :due_date, :client_short_name

field :file_type, 2, "1-2", :file_type
field :account_number, 15, "3-17", :account_number

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we split this to

  • bank number 2
  • branch number 4
  • account number 7

or at least

  • bank + branch number 6
  • account number 7

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do want to split up the account number, we'll have to split out the suffix as well. However for ease of use I think we should keep the branch/branch number, unique number and suffix together, as that is how most New Zealanders use it, and I don't see much benefit in doing so (apart from keeping close relation to the fields in the ASB docs)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I dont hv experience of dealing wih NZ bank transfer

coz in our split app's bank_account model, we have branch_code and account_number (used as BSB and A/C), so I would imagine we could do sth similar for NZ

if we decide to use one field for all related account number in the gem, then we need to figure out the mapping in our adapter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think we'll figure out that mapping in the app. It should be pretty simple (just concatenating the two numbers together). We'll already be doing the reverse (splitting the branch_code and account_number from a larger account number) as we've decided on only showing the account number in the UI/API when in NZ

@zachingle zachingle requested review from corroded May 23, 2022 23:49
Copy link
Contributor

@chris-teague chris-teague left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few thoughts:

  • Fixy seems to suit what we're doing well
  • It's a small & relatively inactive gem, which concerns me a little
    • but, it's codebase is small, easy enough to follow & something we could easily extend / support if needed
  • I'm not sure I like using Fixy formatters for validations - it's going to get clunky & have a lot of repetition once we add the DetailRecords too.
    • To that end - I'm thinking that we should probably use DryRB Validations in the initializer (i.e. have a Contract for HeaderRecord, DetailRecord etc, if it isn't met, return the error object)

@zachingle zachingle changed the title Add header record using Fixy gem Add header record using Fixy and DryRB Validation gems May 24, 2022
@zachingle
Copy link
Contributor Author

A few thoughts:

  • Fixy seems to suit what we're doing well

  • It's a small & relatively inactive gem, which concerns me a little

    • but, it's codebase is small, easy enough to follow & something we could easily extend / support if needed
  • I'm not sure I like using Fixy formatters for validations - it's going to get clunky & have a lot of repetition once we add the DetailRecords too.

    • To that end - I'm thinking that we should probably use DryRB Validations in the initializer (i.e. have a Contract for HeaderRecord, DetailRecord etc, if it isn't met, return the error object)

PR Updated to reflect new approach. I like this a lot more compared to just using Fixy. I've raised a validation error for when the data is invalid so it fails fast. We still need to figure out how we can share the account number schema/rule between the header and detail record. dry-validaton does support inheritance of contracts but IDK if we can pull out single rules

@zachingle zachingle force-pushed the zi/ZEP-1944-fixy-gem branch from 0649bf3 to 07a98a1 Compare May 24, 2022 00:49
@zachingle zachingle requested a review from gzzengwei May 24, 2022 03:31
@zachingle zachingle marked this pull request as ready for review May 24, 2022 03:52
@zachingle zachingle force-pushed the zi/ZEP-1944-fixy-gem branch from ff43a0f to 7fd5cd1 Compare May 24, 2022 05:36
Enabled: false

Layout/LineLength:
Max: 120

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should probs copy the current rubocop yml we have in zfp and split(main zepto) repos

AllCops:
NewCops: enable
TargetRubyVersion: 2.6
TargetRubyVersion: 2.7

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason we're not in 3.0.3 land?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the version specified in the gemspec, and I think it's best if the gem can support as wide a range of Ruby versions as possible (albeit support for 2.7 will be dropped in 10 months)

field :filler109, 109, "52-160", :alphanumeric

field_value :filler5, SPACE * 5
field_value :filler109, SPACE * 109

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of "magic numbers" here. I would try to name them here and make them constants. i.e. 109 could be SOMETHING_FILLER_COUNT / MAYBE_FILLER_PADDING or something so when we use them, it kinda sort of gives us context what it is (and that we should not be able to change it easily):

Suggested change
field_value :filler109, SPACE * 109
field_value :filler109, SPACE * MAYBE_FILLER_PADDING

Copy link
Contributor

@chris-teague chris-teague left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @zachingle! Just a couple of small suggestions / things to look into, but nothing that should block merging from my perspective - we can always raise a seperate PR if needed. 🔥


rule(:account_number).validate(:is_account_number?)

rule(:due_date) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking we should also have a check to see whether a valid due date has been supplied.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, to simplify validation we could change due_date to receive a Date object instead of a string

required(:file_type).filled(:string, included_in?: MT9::Values::FILE_TYPES)
required(:account_number).filled(:string)
required(:due_date).filled(:string)
optional(:client_short_name).value(:string, size?: 0..20)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering whether we want to make this required, even though this isn't strictly the case when looking at the docs? It'd be good to know whether it's a big no-no to send a file without a short name & add a little protection if so

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be a @henripryde400 question to ask to the ASB guys

module Validators
class BaseContract < Dry::Validation::Contract
register_macro(:is_account_number?) do
key.failure("must be 15 or 16 numeric characters") unless /^(\d{15}|\d{16})$/.match(value)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
key.failure("must be 15 or 16 numeric characters") unless /^(\d{15}|\d{16})$/.match(value)
key.failure("must be 15 or 16 numeric characters") unless /^(\d{15,16})$/.match(value)

nitpick, but shorter :) See: https://rubular.com/r/PAUYXnL7M2LDDv

rule(:account_number).validate(:is_account_number?)

rule(:due_date) do
key.failure("must be 6 or 8 numeric characters") unless /^(\d{6}|\d{8})$/.match(value)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
key.failure("must be 6 or 8 numeric characters") unless /^(\d{6}|\d{8})$/.match(value)
key.failure("must be 6 or 8 numeric characters") unless /^(\d{6,8}$/.match(value)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This notation is used for a range (i.e 6 to 8 digits). Here we want either 6 or 8, but not 7 digits

RESERVED_BANK_CODES = %w[99].freeze

DIRECT_CREDIT = "12"
DIRECT_DEBIT = "20"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious why they are strings and not integers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought process here was that we don't perform any integer-like operations on these numbers and these are identifiers, just like the account number, and so are better represented as strings

Copy link

@corroded corroded left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

@SmileAndCompile SmileAndCompile merged commit ac725c6 into main May 24, 2022
@zachingle zachingle mentioned this pull request May 27, 2022
@chrisixion chrisixion deleted the zi/ZEP-1944-fixy-gem branch May 27, 2022 01:36
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants