A fixed budget project bucket. This is a specialisation of Surplus, so any funds classified with this bucket are also considered surplus funds as well. This is a bucket used to represent a large but short lived project that should not exceed a budgeted amount. Using this bucket helps track progress against a budgeted amount for the project.
Inheritance: SurplusBucket
        /// <summary>
        ///     Creates the new fixed budget project.
        /// </summary>
        /// <param name="bucketCode">The bucket code.</param>
        /// <param name="description">The description.</param>
        /// <param name="fixedBudgetAmount">The fixed budget amount.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">
        /// </exception>
        /// <exception cref="ArgumentException">
        ///     The fixed budget amount must be greater than zero.
        ///     or
        ///     A new fixed budget project bucket cannot be created, because the code  + bucketCode +  already exists.
        /// </exception>
        public FixedBudgetProjectBucket CreateNewFixedBudgetProject(string bucketCode, string description,
                                                                    decimal fixedBudgetAmount)
        {
            if (string.IsNullOrWhiteSpace(bucketCode))
            {
                throw new ArgumentNullException(nameof(bucketCode));
            }

            if (string.IsNullOrWhiteSpace(description))
            {
                throw new ArgumentNullException(nameof(description));
            }

            if (fixedBudgetAmount <= 0)
            {
                throw new ArgumentException("The fixed budget amount must be greater than zero.",
                                            nameof(fixedBudgetAmount));
            }

            var upperCode = FixedBudgetProjectBucket.CreateCode(bucketCode);

            if (IsValidCode(upperCode))
            {
                throw new ArgumentException(
                          "A new fixed budget project bucket cannot be created, because the code " + bucketCode +
                          " already exists.", bucketCode);
            }

            lock (this.syncRoot)
            {
                if (IsValidCode(upperCode))
                {
                    throw new ArgumentException(
                              "A new fixed budget project bucket cannot be created, because the code " + bucketCode +
                              " already exists.", bucketCode);
                }

                var bucket = new FixedBudgetProjectBucket(bucketCode, description, fixedBudgetAmount);
                this.lookupTable.Add(upperCode, bucket);
                return(bucket);
            }
        }
        /// <summary>
        ///     Removes the fixed budget project bucket permanently
        /// </summary>
        /// <param name="projectBucket">The project bucket to remove.</param>
        public void RemoveFixedBudgetProject(FixedBudgetProjectBucket projectBucket)
        {
            if (projectBucket == null)
            {
                throw new ArgumentNullException(nameof(projectBucket));
            }

            lock (this.syncRoot)
            {
                if (!IsValidCode(projectBucket.Code))
                {
                    throw new ArgumentException("Unable to remove the fixed project bucket, it does not appear to exist in the bucket repository.");
                }

                if (!this.lookupTable.Remove(projectBucket.Code))
                {
                    throw new InvalidOperationException("Unable to remove the fixed project bucket, removal from the internal dictionary failed. " + projectBucket.Code);
                }
            }
        }
        /// <summary>
        ///     Creates the new fixed budget project.
        /// </summary>
        /// <param name="bucketCode">The bucket code.</param>
        /// <param name="description">The description.</param>
        /// <param name="fixedBudgetAmount">The fixed budget amount.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">
        /// </exception>
        /// <exception cref="ArgumentException">
        ///     The fixed budget amount must be greater than zero.
        ///     or
        ///     A new fixed budget project bucket cannot be created, because the code  + bucketCode +  already exists.
        /// </exception>
        public FixedBudgetProjectBucket CreateNewFixedBudgetProject(string bucketCode, string description,
                                                                    decimal fixedBudgetAmount)
        {
            if (string.IsNullOrWhiteSpace(bucketCode))
            {
                throw new ArgumentNullException(nameof(bucketCode));
            }

            if (string.IsNullOrWhiteSpace(description))
            {
                throw new ArgumentNullException(nameof(description));
            }

            if (fixedBudgetAmount <= 0)
            {
                throw new ArgumentException("The fixed budget amount must be greater than zero.",
                    nameof(fixedBudgetAmount));
            }

            var upperCode = FixedBudgetProjectBucket.CreateCode(bucketCode);
            if (IsValidCode(upperCode))
            {
                throw new ArgumentException(
                    "A new fixed budget project bucket cannot be created, because the code " + bucketCode +
                    " already exists.", bucketCode);
            }

            lock (this.syncRoot)
            {
                if (IsValidCode(upperCode))
                {
                    throw new ArgumentException(
                        "A new fixed budget project bucket cannot be created, because the code " + bucketCode +
                        " already exists.", bucketCode);
                }

                var bucket = new FixedBudgetProjectBucket(bucketCode, description, fixedBudgetAmount);
                this.lookupTable.Add(upperCode, bucket);
                return bucket;
            }
        }
        /// <summary>
        ///     Removes the fixed budget project bucket permanently
        /// </summary>
        /// <param name="projectBucket">The project bucket to remove.</param>
        public void RemoveFixedBudgetProject(FixedBudgetProjectBucket projectBucket)
        {
            if (projectBucket == null)
            {
                throw new ArgumentNullException(nameof(projectBucket));
            }

            lock (this.syncRoot)
            {
                if (!IsValidCode(projectBucket.Code))
                {
                    throw new ArgumentException(
                        "Unable to remove the fixed project bucket, it does not appear to exist in the bucket repository.");
                }

                if (!this.lookupTable.Remove(projectBucket.Code))
                {
                    throw new InvalidOperationException(
                        "Unable to remove the fixed project bucket, removal from the internal dictionary failed. " +
                        projectBucket.Code);
                }
            }
        }