CRM zawiera własny typ danych definiujący pieniądze – Money. Nie należy ona do najmilszych z korzystania, oczywiście dla chcącego nic trudnego, ale Money to po prostu decimal tylko, że opakowany w klasę.

Kod rozszerzeń konwertujących int, int?, decimal, decimal? do Money, i Money do decimal?:

using Microsoft.Xrm.Sdk;

namespace Gutek.Utils.Crm
{
    public static class MoneyExtensions
    {
        public static Money ToMoney(this decimal? @this)
        {
            if([email protected])
            {
                return null;
            }

            return @this.Value.ToMoney();
        }

        public static Money ToMoney(this int? @this)
        {
            if([email protected])
            {
                return null;
            }

            return @this.Value.ToMoney();
        }

        public static Money ToMoney(this decimal @this)
        {
            return new Money(@this);
        }

        public static Money ToMoney(this int @this)
        {
            return new Money(@this);
        }

        public static decimal? ToDecimal(this Money @this)
        {
            if(@this == null)
            {
                return null;
            }

            return @this.Value;
        }
    }
}

Kod testów:

using System;
using Gutek.Utils.Crm;
using Microsoft.Xrm.Sdk;
using Xunit;

namespace Gutek.Utils.Tests.Crm
{
    public class money_extensions_tests
    {
        protected decimal? _nullDecimal = default(Nullable<decimal>);
        protected int? _nullInt = default(Nullable<int>);

        protected decimal? _notNullDecimal = 10;
        protected int? _notNullInt = 10;

        protected int _valueInt = 10;
        protected decimal _valueDecimal = 10;

        protected Money _nullMoney = null;
        protected Money _valueMoney = new Money(10);
    }

    public class to_money_tests : money_extensions_tests
    {
        [Fact]
        public void should_return_null_for_null_number_values()
        {
            Assert.Null(_nullDecimal.ToMoney());
            Assert.Null(_nullInt.ToMoney());
        }

        [Fact]
        public void should_return_money_type_for_not_null_nullable_number_values()
        {
            var dec = _notNullDecimal.ToMoney();
            var i = _notNullInt.ToMoney();

            Assert.NotNull(dec);
            Assert.NotNull(i);

            Assert.Equal(_notNullDecimal.Value, dec.Value);
            Assert.Equal(_notNullInt.Value, dec.Value);
        }

        [Fact]
        public void should_return_money_type_for_not_null_number_values()
        {
            var dec = _valueDecimal.ToMoney();
            var i = _valueInt.ToMoney();

            Assert.NotNull(dec);
            Assert.NotNull(i);

            Assert.Equal(_valueDecimal, dec.Value);
            Assert.Equal(_valueInt, dec.Value);
        }
    }

    public class to_decimal_tests : money_extensions_tests
    {
        [Fact]
        public void should_return_null_for_null_money()
        {
            Assert.Null(_nullMoney.ToDecimal());
        }

        [Fact]
        public void should_return_decimal_for_not_null_money()
        {
            var dec = _valueMoney.ToDecimal();

            Assert.NotNull(dec);

            Assert.Equal(_valueMoney.Value, dec.Value);
        }
    }
}