@@ -117,7 +117,10 @@ public void validateForCreate(final JsonCommand command) {
117117
118118 final BigDecimal transferAmount = this .fromApiJsonHelper
119119 .extractBigDecimalWithLocaleNamed (StandingInstructionApiConstants .amountParamName , element );
120- baseDataValidator .reset ().parameter (StandingInstructionApiConstants .amountParamName ).value (transferAmount ).positiveAmount ();
120+
121+ if (transferAmount != null ) {
122+ baseDataValidator .reset ().parameter (StandingInstructionApiConstants .amountParamName ).value (transferAmount ).positiveAmount ();
123+ }
121124
122125 final Integer transferType = this .fromApiJsonHelper .extractIntegerNamed (transferTypeParamName , element , Locale .getDefault ());
123126 baseDataValidator .reset ().parameter (transferTypeParamName ).value (transferType ).notNull ().inMinMaxRange (1 , 3 );
@@ -132,40 +135,56 @@ public void validateForCreate(final JsonCommand command) {
132135 baseDataValidator .reset ().parameter (StandingInstructionApiConstants .instructionTypeParamName ).value (standingInstructionType )
133136 .notNull ().inMinMaxRange (1 , 2 );
134137
138+ if (isAmountRequired (standingInstructionType )) {
139+ baseDataValidator .reset ().parameter (StandingInstructionApiConstants .amountParamName ).value (transferAmount ).notNull ();
140+ }
141+
135142 final Integer recurrenceType = this .fromApiJsonHelper .extractIntegerNamed (StandingInstructionApiConstants .recurrenceTypeParamName ,
136143 element , Locale .getDefault ());
137- baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceTypeParamName ).value (recurrenceType ).notNull ()
138- .inMinMaxRange (1 , 2 );
144+
145+ if (isRecurrenceRequired (standingInstructionType )) {
146+ baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceTypeParamName ).value (recurrenceType ).notNull ()
147+ .inMinMaxRange (1 , 2 );
148+ }
149+
139150 boolean isPeriodic = false ;
140151 if (recurrenceType != null ) {
141152 isPeriodic = AccountTransferRecurrenceType .fromInt (recurrenceType ).isPeriodicRecurrence ();
142153 }
143154
144155 final Integer recurrenceFrequency = this .fromApiJsonHelper
145156 .extractIntegerNamed (StandingInstructionApiConstants .recurrenceFrequencyParamName , element , Locale .getDefault ());
146- baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceFrequencyParamName ).value (recurrenceFrequency )
147- .inMinMaxRange (0 , 3 );
157+
158+ if (isRecurrenceRequired (standingInstructionType )) {
159+ baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceFrequencyParamName ).value (recurrenceFrequency )
160+ .inMinMaxRange (1 , 3 );
161+ }
148162
149163 if (recurrenceFrequency != null ) {
150164 PeriodFrequencyType frequencyType = PeriodFrequencyType .fromInt (recurrenceFrequency );
151- if (frequencyType .isMonthly () || frequencyType .isYearly ()) {
165+ if (frequencyType != null && ( frequencyType .isMonthly () || frequencyType .isYearly () )) {
152166 final MonthDay monthDay = this .fromApiJsonHelper
153167 .extractMonthDayNamed (StandingInstructionApiConstants .recurrenceOnMonthDayParamName , element );
154- baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceOnMonthDayParamName ).value (monthDay )
155- .notNull ();
168+
169+ if (isRecurrenceRequired (standingInstructionType )) {
170+ baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceOnMonthDayParamName ).value (monthDay )
171+ .notNull ();
172+ }
156173 }
157174 }
158175
159176 final Integer recurrenceInterval = this .fromApiJsonHelper
160177 .extractIntegerNamed (StandingInstructionApiConstants .recurrenceIntervalParamName , element , Locale .getDefault ());
161178 if (isPeriodic ) {
162- baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceIntervalParamName ).value (recurrenceInterval )
163- .notNull ();
164- baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceFrequencyParamName ).value (recurrenceFrequency )
165- .notNull ();
179+ if (isRecurrenceRequired (standingInstructionType )) {
180+ baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceIntervalParamName ).value (recurrenceInterval )
181+ .notNull ();
182+ baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceFrequencyParamName ).value (recurrenceFrequency )
183+ .notNull ();
184+ baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceIntervalParamName ).value (recurrenceInterval )
185+ .integerGreaterThanZero ();
186+ }
166187 }
167- baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceIntervalParamName ).value (recurrenceInterval )
168- .integerGreaterThanZero ();
169188
170189 final String name = this .fromApiJsonHelper .extractStringNamed (StandingInstructionApiConstants .nameParamName , element );
171190 baseDataValidator .reset ().parameter (StandingInstructionApiConstants .nameParamName ).value (name ).notNull ();
@@ -178,7 +197,7 @@ public void validateForCreate(final JsonCommand command) {
178197 .inMinMaxRange (1 , 1 );
179198
180199 }
181- if (standingInstructionType != null && StandingInstructionType . fromInt (standingInstructionType ). isFixedAmoutTransfer ( )) {
200+ if (isAmountRequired (standingInstructionType )) {
182201 baseDataValidator .reset ().parameter (StandingInstructionApiConstants .amountParamName ).value (transferAmount ).notNull ();
183202 }
184203
@@ -230,10 +249,22 @@ public void validateForUpdate(final JsonCommand command) {
230249 baseDataValidator .reset ().parameter (StandingInstructionApiConstants .validTillParamName ).value (validTill ).notNull ();
231250 }
232251
252+ Integer standingInstructionType = null ;
253+ if (this .fromApiJsonHelper .parameterExists (StandingInstructionApiConstants .instructionTypeParamName , element )) {
254+ standingInstructionType = this .fromApiJsonHelper .extractIntegerNamed (StandingInstructionApiConstants .instructionTypeParamName ,
255+ element , Locale .getDefault ());
256+ baseDataValidator .reset ().parameter (StandingInstructionApiConstants .instructionTypeParamName ).value (standingInstructionType )
257+ .notNull ().inMinMaxRange (1 , 2 );
258+ }
259+
233260 if (this .fromApiJsonHelper .parameterExists (StandingInstructionApiConstants .amountParamName , element )) {
234261 final BigDecimal transferAmount = this .fromApiJsonHelper
235262 .extractBigDecimalWithLocaleNamed (StandingInstructionApiConstants .amountParamName , element );
236263 baseDataValidator .reset ().parameter (StandingInstructionApiConstants .amountParamName ).value (transferAmount ).positiveAmount ();
264+
265+ if (isAmountRequired (standingInstructionType )) {
266+ baseDataValidator .reset ().parameter (StandingInstructionApiConstants .amountParamName ).value (transferAmount ).notNull ();
267+ }
237268 }
238269
239270 if (this .fromApiJsonHelper .parameterExists (StandingInstructionApiConstants .statusParamName , element )) {
@@ -250,13 +281,6 @@ public void validateForUpdate(final JsonCommand command) {
250281 .inMinMaxRange (1 , 4 );
251282 }
252283
253- if (this .fromApiJsonHelper .parameterExists (StandingInstructionApiConstants .instructionTypeParamName , element )) {
254- final Integer standingInstructionType = this .fromApiJsonHelper
255- .extractIntegerNamed (StandingInstructionApiConstants .instructionTypeParamName , element , Locale .getDefault ());
256- baseDataValidator .reset ().parameter (StandingInstructionApiConstants .instructionTypeParamName ).value (standingInstructionType )
257- .notNull ().inMinMaxRange (1 , 2 );
258- }
259-
260284 if (this .fromApiJsonHelper .parameterExists (StandingInstructionApiConstants .recurrenceTypeParamName , element )) {
261285 final Integer recurrenceType = this .fromApiJsonHelper
262286 .extractIntegerNamed (StandingInstructionApiConstants .recurrenceTypeParamName , element , Locale .getDefault ());
@@ -274,8 +298,11 @@ public void validateForUpdate(final JsonCommand command) {
274298 if (this .fromApiJsonHelper .parameterExists (StandingInstructionApiConstants .recurrenceIntervalParamName , element )) {
275299 final Integer recurrenceInterval = this .fromApiJsonHelper
276300 .extractIntegerNamed (StandingInstructionApiConstants .recurrenceIntervalParamName , element , Locale .getDefault ());
277- baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceIntervalParamName ).value (recurrenceInterval )
278- .integerGreaterThanZero ();
301+
302+ if (isRecurrenceRequired (standingInstructionType )) {
303+ baseDataValidator .reset ().parameter (StandingInstructionApiConstants .recurrenceIntervalParamName ).value (recurrenceInterval )
304+ .integerGreaterThanZero ();
305+ }
279306 }
280307
281308 if (this .fromApiJsonHelper .parameterExists (StandingInstructionApiConstants .nameParamName , element )) {
@@ -291,4 +318,40 @@ private void throwExceptionIfValidationWarningsExist(final List<ApiParameterErro
291318 throw new PlatformApiDataValidationException (dataValidationErrors );
292319 }
293320 }
321+
322+ // ============================================
323+ // PRIVATE HELPER METHODS
324+ // ============================================
325+
326+ /**
327+ * Determines if the standing instruction type requires amount validation. Amount is required only for
328+ * FIXED_AMOUNT_TRANSFER type. For DUES type, amount is calculated based on outstanding dues.
329+ *
330+ * @param standingInstructionType
331+ * the instruction type code
332+ * @return true if amount validation is required, false otherwise
333+ */
334+ private boolean isAmountRequired (Integer standingInstructionType ) {
335+ if (standingInstructionType == null ) {
336+ return false ;
337+ }
338+ StandingInstructionType type = StandingInstructionType .fromInt (standingInstructionType );
339+ return type != null && type .isFixedAmoutTransfer ();
340+ }
341+
342+ /**
343+ * Determines if recurrence fields should be validated. Recurrence is required for all types except DUES. DUES
344+ * instructions are processed based on loan due dates, not recurrence pattern.
345+ *
346+ * @param standingInstructionType
347+ * the instruction type code
348+ * @return true if recurrence validation is required, false otherwise
349+ */
350+ private boolean isRecurrenceRequired (Integer standingInstructionType ) {
351+ if (standingInstructionType == null ) {
352+ return true ;
353+ }
354+ StandingInstructionType type = StandingInstructionType .fromInt (standingInstructionType );
355+ return type != null && !type .isDuesAmoutTransfer ();
356+ }
294357}
0 commit comments