public void CannotReleaseInvalidReservations()
        {
            var unitStoreMock     = new UnitStoreMock();
            var customerStoreMock = new CustomerStoreMock();
            var tenancyStoreMock  = new TenancyStoreMock();
            var dateServiceMock   = new DateServiceMock();
            var facade            = new Facade(unitStoreMock, customerStoreMock, tenancyStoreMock, dateServiceMock);

            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber = "A1"
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Alpha"
            });
            Assert.Throws <InvalidOperationException>(() =>
            {
                facade.ReleaseUnit("A1", "Alpha");
            });
            facade.ReserveUnit("A1", "Alpha");
            facade.ReleaseUnit("A1", "Alpha");
            Assert.Throws <InvalidOperationException>(() =>
            {
                facade.ReleaseUnit("A1", "Alpha");
            });
        }
        public void CommissionedUnitCubicFeetShouldNotExceedIntMaxValue()
        {
            var unitStoreMock    = new UnitStoreMock();
            var tenancyStoreMock = new TenancyStoreMock();
            var facade           = new Facade(unitStoreMock, new CustomerStoreDummy(), tenancyStoreMock, new DateServiceDummy());

            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "1A",
                Length              = 10,
                Width               = 10,
                Height              = 10,
                IsClimateControlled = true,
                IsVehicleAccessible = true,
                PricePerMonth       = 90
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "2B",
                IsClimateControlled = true,
                IsVehicleAccessible = true,
                PricePerMonth       = 90
            });


            var failUnit1 = new NewUnit()
            {
                UnitNumber          = "3C",
                Length              = int.MaxValue / 2,
                Width               = int.MaxValue / 2,
                Height              = 2,
                IsClimateControlled = false,
                IsVehicleAccessible = false,
            };

            Assert.Throws <ArgumentOutOfRangeException>(() => facade.CommissionNewUnit(failUnit1));

            var failUnit2 = new NewUnit()
            {
                UnitNumber          = "4B",
                Length              = 1,
                IsClimateControlled = false,
                IsVehicleAccessible = false,
            };

            Assert.Throws <ArgumentException>(() => facade.CommissionNewUnit(failUnit2));

            var failUnit3 = new NewUnit()
            {
                UnitNumber          = "4B",
                Length              = 1,
                Width               = 5,
                Height              = 0,
                IsClimateControlled = false,
                IsVehicleAccessible = false,
            };

            Assert.Throws <ArgumentException>(() => facade.CommissionNewUnit(failUnit3));
        }
        public void Scenario2()
        {
            var unitStoreMock     = new UnitStoreMock();
            var customerStoreMock = new CustomerStoreMock();
            var tenancyStoreMock  = new TenancyStoreMock();
            var dateServiceMock   = new DateServiceMock();
            var facade            = new Facade(unitStoreMock, customerStoreMock, tenancyStoreMock, dateServiceMock);

            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "A1",
                Length              = 2,
                Width               = 2,
                Height              = 2,
                IsClimateControlled = true,
                IsVehicleAccessible = false,
                PricePerMonth       = 20
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "B2",
                Length              = 8,
                Width               = 8,
                Height              = 8,
                IsClimateControlled = false,
                IsVehicleAccessible = true,
                PricePerMonth       = 80
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Alpha"
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Bravo"
            });
            dateServiceMock.CurrentDateTime = new DateTime(2017, 01, 01);
            facade.ReserveUnit("A1", "Alpha");
            facade.ReserveUnit("B2", "Alpha");
            dateServiceMock.CurrentDateTime = new DateTime(2017, 03, 01);
            Assert.Equal(200, facade.CalculateAmountDue("Alpha"));
            facade.Pay("Alpha", 150);
            Assert.Equal(50, facade.CalculateAmountDue("Alpha"));
            dateServiceMock.CurrentDateTime = new DateTime(2017, 04, 01);
            Assert.Equal(150, facade.CalculateAmountDue("Alpha"));
            facade.Pay("Alpha", 50);
            Assert.Equal(100, facade.CalculateAmountDue("Alpha"));
            facade.Pay("Alpha", 120.43m);
            Assert.Equal(0, facade.CalculateAmountDue("Alpha"));
            dateServiceMock.CurrentDateTime = new DateTime(2017, 05, 01);
            Assert.Equal(100, facade.CalculateAmountDue("Alpha"));
            facade.Pay("Alpha", 100);
            Assert.Equal(0, facade.CalculateAmountDue("Alpha"));
            dateServiceMock.CurrentDateTime = new DateTime(2018, 02, 01);
            Assert.Equal(900, facade.CalculateAmountDue("Alpha"));
            facade.Pay("Alpha", 900);
            Assert.Equal(0, facade.CalculateAmountDue("Alpha"));
        }
        public void RejectsDuplicateUnits()
        {
            var unitStoreMock = new UnitStoreMock();
            var facade        = new Facade(unitStoreMock, new CustomerStoreDummy(), new TenancyStoreDummy(), new DateServiceDummy());

            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber = "Number"
            });
            Assert.Throws <InvalidOperationException>(() =>
            {
                facade.CommissionNewUnit(new NewUnit()
                {
                    UnitNumber = "Number"
                });
            });
        }
        public void CommissionsAndDecommissionsUnitsCorrectly()
        {
            var unitStoreMock    = new UnitStoreMock();
            var tenancyStoreMock = new TenancyStoreMock();
            var facade           = new Facade(unitStoreMock, new CustomerStoreDummy(), tenancyStoreMock, new DateServiceDummy());

            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "1A",
                Length              = 10,
                Width               = 12,
                Height              = 14,
                IsClimateControlled = true,
                IsVehicleAccessible = true,
                PricePerMonth       = 90
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "2B",
                IsClimateControlled = false,
                IsVehicleAccessible = false,
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "3C",
                IsClimateControlled = true,
                IsVehicleAccessible = false,
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "4D",
                IsClimateControlled = false,
                IsVehicleAccessible = true,
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "5E",
                IsClimateControlled = false,
                IsVehicleAccessible = false,
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "6F",
                IsClimateControlled = false,
                IsVehicleAccessible = false,
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber = "7G"
            });
            facade.DecommissionUnit("7G");
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber = "8H"
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber = "9I"
            });
            facade.DecommissionUnit("8H");
            Assert.Equal(7, unitStoreMock.Units.Count);
            var unit = unitStoreMock.Units.Single(u => u.UnitNumber == "1A");

            Assert.Equal(10, unit.Length);
            Assert.Equal(12, unit.Width);
            Assert.Equal(14, unit.Height);
            Assert.True(unit.IsClimateControlled);
            Assert.True(unit.IsVehicleAccessible);
            Assert.Equal(90, unit.PricePerMonth);
            var unitNumbers = unitStoreMock.Units.Select(u => u.UnitNumber).ToArray();

            Assert.Contains("2B", unitNumbers);
            Assert.Contains("3C", unitNumbers);
            Assert.Contains("4D", unitNumbers);
            Assert.Contains("5E", unitNumbers);
            Assert.Contains("6F", unitNumbers);
            Assert.Contains("9I", unitNumbers);
        }
        public void Scenario1()
        {
            var unitStoreMock     = new UnitStoreMock();
            var customerStoreMock = new CustomerStoreMock();
            var tenancyStoreMock  = new TenancyStoreMock();
            var dateServiceMock   = new DateServiceMock();
            var facade            = new Facade(unitStoreMock, customerStoreMock, tenancyStoreMock, dateServiceMock);

            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "A1",
                Length              = 5,
                Width               = 5,
                Height              = 8,
                IsClimateControlled = false,
                IsVehicleAccessible = true,
                PricePerMonth       = 50
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "B2",
                Length              = 10,
                Width               = 5,
                Height              = 8,
                IsClimateControlled = false,
                IsVehicleAccessible = true,
                PricePerMonth       = 60
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "C3",
                Length              = 10,
                Width               = 10,
                Height              = 8,
                IsClimateControlled = false,
                IsVehicleAccessible = true,
                PricePerMonth       = 70
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "D4",
                Length              = 4,
                Width               = 4,
                Height              = 4,
                IsClimateControlled = true,
                IsVehicleAccessible = false,
                PricePerMonth       = 100
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "E5",
                Length              = 6,
                Width               = 6,
                Height              = 6,
                IsClimateControlled = true,
                IsVehicleAccessible = false,
                PricePerMonth       = 110
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "F6",
                Length              = 8,
                Width               = 8,
                Height              = 8,
                IsClimateControlled = true,
                IsVehicleAccessible = false,
                PricePerMonth       = 120
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Alpha"
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Bravo"
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Charlie"
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Delta"
            });

            facade.UpdateCustomerDetails(new NewCustomer()
            {
                CustomerNumber = "Delta", FullName = "Delta Delta", Address = "Address"
            });

            Assert.Empty(facade.GetCustomerUnits("Alpha"));
            Assert.Empty(facade.GetCustomerUnits("Bravo"));
            Assert.Empty(facade.GetCustomerUnits("Charlie"));

            var details = facade.GetCustomerDetails("Delta");

            Assert.Equal("Delta", details.CustomerNumber);
            Assert.Equal("Delta Delta", details.FullName);
            Assert.Equal("Address", details.Address);

            var find1 = facade.SearchAvailableUnits(null, null, null).ToArray();

            Assert.Equal(6, find1.Length);
            var find2 = facade.SearchAvailableUnits(true, null, 70).ToArray();

            Assert.Equal(2, find2.Length);
            var find3 = facade.SearchAvailableUnits(null, true, 750).ToArray();

            Assert.Single(find3);
            var unit = find3.Single();

            Assert.Equal("C3", unit.UnitNumber);
            dateServiceMock.CurrentDateTime = new DateTime(2017, 01, 01);
            facade.ReserveUnit("C3", "Charlie");

            var charliesUnits = facade.GetCustomerUnits("Charlie");

            Assert.Single(charliesUnits);
            Assert.True(charliesUnits.Single().UnitNumber == "C3");
            Assert.True(charliesUnits.Single().ReservationDate == new DateTime(2017, 01, 01));
            Assert.True(charliesUnits.Single().AmountPaid == 0);

            dateServiceMock.CurrentDateTime = new DateTime(2017, 03, 01);
            Assert.Equal(140, facade.CalculateAmountDue("Charlie"));
            dateServiceMock.CurrentDateTime = new DateTime(2017, 04, 01);
            Assert.Equal(210, facade.CalculateAmountDue("Charlie"));
            facade.Pay("Charlie", 180);
            Assert.Equal(30, facade.CalculateAmountDue("Charlie"));
            dateServiceMock.CurrentDateTime = new DateTime(2017, 05, 01);
            Assert.Equal(100, facade.CalculateAmountDue("Charlie"));
            facade.Pay("Charlie", 100);
            Assert.Equal(0, facade.CalculateAmountDue("Charlie"));
            dateServiceMock.CurrentDateTime = new DateTime(2017, 06, 01);
            Assert.Equal(70, facade.CalculateAmountDue("Charlie"));
            var find4 = facade.SearchAvailableUnits(null, true, 750).ToArray();

            Assert.Empty(find4);
            facade.Pay("Charlie", 70);
            facade.ReleaseUnit("C3", "Charlie");
            dateServiceMock.CurrentDateTime = new DateTime(2017, 07, 01);
            Assert.Equal(0, facade.CalculateAmountDue("Charlie"));
            var find5 = facade.SearchAvailableUnits(null, true, 750).ToArray();

            Assert.Single(find5);
            var find6 = facade.SearchAvailableUnits(null, null, null).ToArray();

            Assert.Equal(6, find6.Length);
            var customerLookup = facade.ListCustomersAndTenants();

            Assert.Equal(4, customerLookup.Count());
        }
        public void CantDeleteCustomersWithReservedUnits()
        {
            var customerStoreMock = new CustomerStoreMock();
            var tenancyStoreMock  = new TenancyStoreMock();
            var unitStoreMock     = new UnitStoreMock();
            var dateServiceMock   = new DateServiceMock();
            var facade            = new Facade(unitStoreMock, customerStoreMock, tenancyStoreMock, dateServiceMock);

            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Alpha",
                FullName       = "Alpha Name",
                Address        = "Alpha Address"
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Bravo",
                FullName       = "Bravo Name",
                Address        = "Bravo Address"
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Charlie",
                FullName       = "Charlie Name",
                Address        = "Charlie Address"
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "1A",
                Length              = 10,
                Width               = 12,
                Height              = 14,
                IsClimateControlled = true,
                IsVehicleAccessible = true,
                PricePerMonth       = 90
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "2B",
                IsClimateControlled = false,
                IsVehicleAccessible = false,
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "3C",
                IsClimateControlled = true,
                IsVehicleAccessible = false,
            });

            dateServiceMock.CurrentDateTime = new DateTime(2017, 01, 01);

            facade.ReserveUnit("1A", "Alpha");
            facade.ReserveUnit("2B", "Bravo");
            facade.ReserveUnit("3C", "Charlie");

            Assert.Throws <InvalidOperationException>(() => facade.DeleteCustomer("Alpha"));
            facade.ReleaseUnit("1A", "Alpha");
            facade.DeleteCustomer("Alpha");
            Assert.Equal(2, customerStoreMock.Customers.Count());

            Assert.Throws <InvalidOperationException>(() => facade.DeleteCustomer("Bravo"));
            facade.ReleaseUnit("2B", "Bravo");
            facade.DeleteCustomer("Bravo");
            Assert.Single(customerStoreMock.Customers);
        }
        public void Scenario1()
        {
            var unitStoreMock     = new UnitStoreMock();
            var customerStoreMock = new CustomerStoreMock();
            var tenancyStoreMock  = new TenancyStoreMock();
            var dateServiceMock   = new DateServiceMock();
            var facade            = new Facade(unitStoreMock, customerStoreMock, tenancyStoreMock, dateServiceMock);

            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "A1",
                Length              = 5,
                Width               = 5,
                Height              = 8,
                IsClimateControlled = false,
                IsVehicleAccessible = true,
                PricePerMonth       = 50
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "B2",
                Length              = 10,
                Width               = 5,
                Height              = 8,
                IsClimateControlled = false,
                IsVehicleAccessible = true,
                PricePerMonth       = 60
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "C3",
                Length              = 10,
                Width               = 10,
                Height              = 8,
                IsClimateControlled = false,
                IsVehicleAccessible = true,
                PricePerMonth       = 70
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "D4",
                Length              = 4,
                Width               = 4,
                Height              = 4,
                IsClimateControlled = true,
                IsVehicleAccessible = false,
                PricePerMonth       = 100
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "E5",
                Length              = 6,
                Width               = 6,
                Height              = 6,
                IsClimateControlled = true,
                IsVehicleAccessible = false,
                PricePerMonth       = 110
            });
            facade.CommissionNewUnit(new NewUnit()
            {
                UnitNumber          = "F6",
                Length              = 8,
                Width               = 8,
                Height              = 8,
                IsClimateControlled = true,
                IsVehicleAccessible = false,
                PricePerMonth       = 120
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Alpha"
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Bravo"
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Charlie"
            });
            facade.AddNewCustomer(new NewCustomer()
            {
                CustomerNumber = "Delta"
            });
            var find1 = facade.FindAvailableUnits(null, null, null).ToArray();

            Assert.Equal(6, find1.Length);
            var find2 = facade.FindAvailableUnits(true, null, 70).ToArray();

            Assert.Equal(2, find2.Length);
            var find3 = facade.FindAvailableUnits(null, true, 750).ToArray();

            Assert.Equal(1, find3.Length);
            var unit = find3.Single();

            Assert.Equal("C3", unit.UnitNumber);
            dateServiceMock.CurrentDateTime = new DateTime(2017, 01, 01);
            facade.ReserveUnit("C3", "Charlie");
            dateServiceMock.CurrentDateTime = new DateTime(2017, 03, 01);
            Assert.Equal(140, facade.CalculateAmountDue("Charlie"));
            dateServiceMock.CurrentDateTime = new DateTime(2017, 04, 01);
            Assert.Equal(210, facade.CalculateAmountDue("Charlie"));
            facade.Pay("Charlie", 180);
            Assert.Equal(30, facade.CalculateAmountDue("Charlie"));
            dateServiceMock.CurrentDateTime = new DateTime(2017, 05, 01);
            Assert.Equal(100, facade.CalculateAmountDue("Charlie"));
            facade.Pay("Charlie", 100);
            Assert.Equal(0, facade.CalculateAmountDue("Charlie"));
            dateServiceMock.CurrentDateTime = new DateTime(2017, 06, 01);
            Assert.Equal(70, facade.CalculateAmountDue("Charlie"));
            var find4 = facade.FindAvailableUnits(null, true, 750).ToArray();

            Assert.Equal(0, find4.Length);
            facade.Pay("Charlie", 70);
            facade.ReleaseUnit("C3", "Charlie");
            dateServiceMock.CurrentDateTime = new DateTime(2017, 07, 01);
            Assert.Equal(0, facade.CalculateAmountDue("Charlie"));
            var find5 = facade.FindAvailableUnits(null, true, 750).ToArray();

            Assert.Equal(1, find5.Length);
            var find6 = facade.FindAvailableUnits(null, null, null).ToArray();

            Assert.Equal(6, find6.Length);
        }