---
# System prepended metadata

title: CD Maturity

---

# CD Maturity


@functions{
public class JsonHelper: IDisposable
{
	private System.Text.Json.JsonDocument _jsonDocument;
	private Dictionary<string, System.Text.Json.JsonElement> _flattened=new Dictionary<string, System.Text.Json.JsonElement>();
	public JsonHelper(object data, bool throwIfNotExist = true)
	{
        try{
            ThrowIfNotExist = throwIfNotExist;

            var options = new System.Text.Json.JsonDocumentOptions()
            {
                AllowTrailingCommas = true,
                CommentHandling = System.Text.Json.JsonCommentHandling.Skip
            };
            _jsonDocument = System.Text.Json.JsonDocument.Parse(Newtonsoft.Json.JsonConvert.SerializeObject(data), options);
            _flattened = GetFlat(_jsonDocument);
        }
        catch(Exception ex){
            throw new InvalidOperationException($"Failed to create JsonDataHelper:{ex.Message}",ex);
        }
	}
	
	public bool ThrowIfNotExist { get; set; }
	
	public string GetFields()
	{
		return string.Join("\n", _flattened.Keys);
	}
	public string GetValue(string path, Func<string,string> formatter=null)
	{
		if (!_validatePath(path, out var error))
			return error;
		
		var value=_flattened[path].GetRawText().Replace("\"","");
		try
		{	        
			return formatter==null? value: formatter(value);
		}
		catch (Exception ex)
		{
			return "ERROR:" + value + " - " + ex.Message;
		}
	}
	public string GetNumber(string path, string format)
	{
		return GetValue(path, value=>double.Parse(value).ToString(format));
	}
    public string GetDate(string path, string inputFormat, string outputFormat)
	{
		return GetValue(path, value=>System.DateTime.ParseExact(value, inputFormat, null).ToString(outputFormat));        
	}
	public string GetArrayElementValue(string path, int index, Func<string,string> formatter=null)
	{
		string value = null;
		try
		{
			if (!path.Contains("[]"))
				throw new InvalidOperationException($"Path:{path} should contain []");

			var closingBracketEnd = path.IndexOf(']') + 1;
			var arrayElementPath = path.Substring(0, closingBracketEnd);
			var propertyName = path.Substring(closingBracketEnd + 1);

			var jsonElement = _getArrayElement(arrayElementPath);

			var arrayLength = jsonElement.GetArrayLength();
			if (index >= arrayLength)
				throw new InvalidOperationException($"Index:{index} is side array length:{arrayLength}");

			var arrayElement = jsonElement.EnumerateArray().Skip(index).First();
			if (!arrayElement.TryGetProperty(propertyName, out var prop))
				throw new InvalidOperationException($"Failed to find field:{propertyName}");
			value = prop.GetRawText().Replace("\"","");
			return formatter == null ?
				value :
				formatter(value);
		}
		catch (Exception ex)
		{
			throw new InvalidOperationException($"{path}|{value} - {ex.Message}",ex);
		}
	}	
	public string GetMdTableValues(string arrayPath, params string[] fields)
	{
		return GetMdTableValues(arrayPath, fields, null);
	}
	public string GetMdTableValues(string arrayPath, string[] fields, string rowPefix, string rowSuffix)
	{
		return GetMdTableValues(arrayPath, fields, null);
	}
	public string GetMdTableValues(string arrayPath, string[] fields, Func<string,string>[] formatCalls, string rowPefix="|", string rowSuffix="|")
	{		
		if (!arrayPath.EndsWith("[]"))
			throw new InvalidOperationException($"Path:{arrayPath} should end with []");
		
		if(formatCalls?.Any()==true && fields.Length!=formatCalls.Length)
			throw new InvalidOperationException("Number of fieds do not match number of formats");
		bool hasFormatters = formatCalls?.Any()==true;
		
		var jsonElement = _getArrayElement(arrayPath);

		var tableBuilder = new System.Text.StringBuilder();
		var index=-1;
		foreach (var element in jsonElement.EnumerateArray())
		{
			index++;
			var rowBuilder = new System.Text.StringBuilder(rowPefix);
			var fieldIndex = -1;
			foreach (var fieldName in fields)
			{
				fieldIndex++;
				if (!element.TryGetProperty(fieldName, out var field))
					continue;
				if(fieldIndex>0)
					rowBuilder.Append("|");
				var value = field.GetRawText().Replace("\"","");
				rowBuilder.Append(!hasFormatters?
					$"{value}":
					$"{formatCalls[index](value)}");
			}
			tableBuilder.Append(rowBuilder.ToString());
			tableBuilder.Append(rowSuffix);
			tableBuilder.AppendLine();
		}

		return tableBuilder.ToString();
	}
	public void Dispose()
	{
		_flattened?.Clear();
		_jsonDocument?.Dispose();
	}
	
	#region Private
	private bool _validatePath(string path, out string error)
	{
		error=null;
		if (!_flattened.ContainsKey(path))
		{
			if (ThrowIfNotExist)
				throw new InvalidOperationException($"Invalid json field:{path}");
			error = "ERROR:" + path;
			return false;
		}
		return true;
	}
	private System.Text.Json.JsonElement _getArrayElement(string arrayPath)
	{
		var jsonElement = _flattened[arrayPath];
		if (jsonElement.ValueKind != System.Text.Json.JsonValueKind.Array)
			throw new InvalidOperationException($"Expected array, but found: {jsonElement.ValueKind} for:{arrayPath}");
		return jsonElement;
	}
	private static Dictionary<string, System.Text.Json.JsonElement> GetFlat(System.Text.Json.JsonDocument document)
	{
		return document.RootElement.EnumerateObject()
			.SelectMany(p => GetLeaves(null, p))
			.ToDictionary(k => k.Path, v => v.P.Value.Clone()); //Clone so that we can use the values outside of using
	}
	private static IEnumerable<(string Path, System.Text.Json.JsonProperty P)> GetLeaves(string path, System.Text.Json.JsonProperty p)
	{
		path = (path == null) ? p.Name : path + "." + p.Name;

		switch (p.Value.ValueKind)
		{
			case System.Text.Json.JsonValueKind.Array:
				var arrayLenght = p.Value.GetArrayLength();
				if (arrayLenght == 0)
					break;
				System.Text.Json.JsonElement firstElement = p.Value.EnumerateArray().First();
				path += "[]";
				yield return (Path: path, P: p);
				foreach (System.Text.Json.JsonProperty child in firstElement.EnumerateObject())
					foreach (var leaf in GetLeaves(path, child))
						yield return leaf;
				break;
			case System.Text.Json.JsonValueKind.Object:
				foreach (System.Text.Json.JsonProperty child in p.Value.EnumerateObject())
					foreach (var leaf in GetLeaves(path, child))
						yield return leaf;
				break;
			case System.Text.Json.JsonValueKind.Null:
			case System.Text.Json.JsonValueKind.Undefined:
				break;
			default:
				yield return (Path: path, P: p);
				break;
		}
	}
	#endregion
}
}

@{
    JsonHelper jsonHelper=null;
    try{
        jsonHelper = new JsonHelper(Model.Sequence.Data,false);
    }
    catch(Exception ex){
        <p>ERROR: @Raw(ex.Message)</p>
    }
}

### Pre-Maturity Disclosure Notice: @jsonHelper.GetValue("technical.corpTypeD")

|  |  |  |
| -------- | -------- | -------- | {.vast}
| @jsonHelper.GetValue("party.nameOne") |||
| @jsonHelper.GetArrayElementValue("party.address[].street",0)|||
| @jsonHelper.GetArrayElementValue("party.address[].city",0)|||
| @jsonHelper.GetArrayElementValue("party.address[].zip",0)|||
| @jsonHelper.GetArrayElementValue("party.address[].state",0) |CD Number |?|
| @jsonHelper.GetArrayElementValue("party.address[].country",0) |Date| @jsonHelper.GetDate("technical.corDateR","M-d-yyyy","MM-dd-yyyy") |

Your Certificate of Deposit number for @jsonHelper.GetValue("account.accountNumber") will **only** mature on @jsonHelper.GetValue("account.term.maturityDate"). If the account renews, the following information will apply:

**RATE INFORMATION:** The **@jsonHelper.GetValue("account.term.interestDistribution")** and annual percentage yield have not yet been determined. They will be available on **@jsonHelper.GetValue("account.term.interestFrequency")** or after @jsonHelper.GetValue("account.term.maturityDate"). Please call ***(918) 495-1700*** to learn the interest rate and annual percentage yield for your new account. Once the Rate is determined, the APY will be in effect until maturity.

**COMPOUNDING AND CREDITING:** Frequency - Interest for your account will be paid @jsonHelper.GetValue("account.term.interestFrequency")  @jsonHelper.GetValue("account.term.interestDistribution")

**EFFECT OF CLOSING AN ACCOUNT:** If you close your account prior to maturity you may be charged an early withdrawal penalty.

**MINIMUM BALANCE REQUIREMENTS TO OPEN THE ACCOUNT:** You must deposit at least @jsonHelper.GetValue("account.term.minimumtoOpen") to open this account and maintain @jsonHelper.GetValue("account.term.minimumtoOpen") to obtain the stated APY.

**BALANCE COMPUTATION METHOD:** We use the daily balance method to calculate the interest on your account. This method applies a daily periodic rate to the principal in the account each day.

**ACCRUAL OF INTEREST ON NONCASH DEPOSITS:** Interest begins to accrue on the business day you deposit noncash items (for example, checks).

**TIME REQUIREMENTS:** Your account will mature in @jsonHelper.GetValue("account.term.termDuration") @jsonHelper.GetValue("account.term.termPeriod")

**TIME DEPOSIT WITHDRAWAL LIMITATIONS:** 

* **Principal:** You may not make withdrawals of principal from your account before maturity without penalty.
* **Interest:** You cannot withdraw interest from your account before maturity. The annual percentage yield assumes interest will remain on deposit until maturity, and a withdrawal will reduce earnings.

**EARLY WITHDRAWAL PENALTY:** 
Certificates with a term of less than three (3) months: The penalty imposed will equal 100% of the accrued interest. The interest rate we will use to calculate the interest forfeiture will be the simple interest rate in effect on the date of early withdrawal.

Certificates with a term of three (3) months to less than twelve (12) months: The penalty imposed will equal three month's interest on the amount withdrawn. The interest rate we will use to calculate the interest forfeiture will be the simple interest rate in effect on the date of early withdrawal.

**AUTOMATICALLY RENEWABLE:** This account will automatically renew at maturity. You will have 10 days after the maturity date to withdraw funds without penalty. This account will not renew if you withdraw the funds on the maturity date or if we receive written notice from you on or before the maturity date of your intention not to renew. We can prevent renewal if we mail notice to you at least 10 days before maturity.

**RENEWAL TERMS:** 
Each renewal term will be the same as the original term, beginning on the maturity date. The interest rate will be the same as we offer on new time deposits on the maturity date which have the same term, minimum balance (if any) and other features  as the original time deposit.

<pre>
@Raw(jsonHelper.GetFields())

</pre>