public void Can_Save_Bill_To_Db()
        {
            // Arrange
            City city = new City(10000, "Zagreb");
            Cadastre cadastre = new Cadastre("Trnje", "12345", city);
            CadastralParticle cadastralParticle = new CadastralParticle(cadastre, "123", 23, "Opis");
            LandRegistry landRegistry = new LandRegistry(cadastralParticle);

            var person = new PhysicalPerson("12345678901", "Ime", "Prezime") {
                Address = new Address("Ulica", "1", city)
            };

            var partitionSpace = landRegistry.CreatePartitionSpace("123", 12, "Opis etaže", person);

            LegalPerson legalPerson = new LegalPerson("12345678902", "Ime") {
                NumberOfBankAccount = "123456",
                Address = new Address("Ulica", "2", city)
            };
            BuildingManager buildingManager = new BuildingManager(legalPerson);

            Building building = new Building(buildingManager) {
                LandRegistry = landRegistry
            };

            Bill bill = new Bill(legalPerson, building.Reserve, "opis plaćanja", 23) {
                ReferenceNumber = "123"
            };
            bill.AddBillItem(new BillItem(1, 12.3m, "Opis"));

            IBillsRepository billsRepository = new BillsNHRepository(SessionFactory);

            // Act
            using (var session = SessionFactory.OpenSession()) {
                using (var transaction = session.BeginTransaction()) {
                    session.Save(city);
                    session.Save(person);
                    session.Save(legalPerson);
                    session.Save(cadastre);
                    session.Save(landRegistry);
                    session.Save(buildingManager);
                    session.Save(building);

                    billsRepository.SaveOrUpdate(bill);

                    transaction.Commit();
                }
            }

            IList<Bill> billsFromDb = null;
            using (var session = SessionFactory.OpenSession()) {
                using (var transaction = session.BeginTransaction()) {
                    billsFromDb = billsRepository.GetAll().ToList();
                    transaction.Commit();
                }
            }

            // Assert
            Assert.IsTrue(billsFromDb.Count == 1, "No Bill from database.");
        }
        public void Can_Read_Reserve_From_Db()
        {
            // Arrange
            City city = new City(10000, "Zagreb");
            Cadastre cadastre = new Cadastre("Trnje", "12345", city);
            CadastralParticle cadastralParticle = new CadastralParticle(cadastre, "123", 23, "Opis");
            LandRegistry landRegistry = new LandRegistry(cadastralParticle);

            var person = new PhysicalPerson("12345678901", "Ime", "Prezime");
            var partitionSpace = landRegistry.CreatePartitionSpace("123", 12, "Opis etaže", person);

            LegalPerson legalPerson = new LegalPerson("12345678902", "Ime") {
                NumberOfBankAccount = "12332213",
                Address = new Address("dsa", "2", city)
            };
            BuildingManager buildingManager = new BuildingManager(legalPerson);

            Building building = new Building(buildingManager) {
                LandRegistry = landRegistry
            };

            Bill bill = new Bill(legalPerson, building.Reserve, "račun", 23) {
                ReferenceNumber = "123"
            };
            building.Reserve.AddBillForPayment(bill);

            // Act
            using (var session = SessionFactory.OpenSession()) {
                using (var transaction = session.BeginTransaction()) {
                    session.Save(city);
                    session.Save(cadastre);
                    session.Save(person);
                    session.Save(landRegistry);
                    session.Save(legalPerson);
                    session.Save(buildingManager);
                    session.Save(building);

                    transaction.Commit();
                }
            }

            IReservesRepository reservesRepository = new ReservesNHRepository(SessionFactory);
            IList<Reserve> reservesFromDb = null;
            using (var session = SessionFactory.OpenSession()) {
                using (var transaction = session.BeginTransaction()) {
                    reservesFromDb = reservesRepository.GetAll().ToList();
                    transaction.Commit();
                }
            }

            // Assert
            Assert.IsTrue(reservesFromDb.Count == 1, "No Reserves from database.");
            //Assert.IsTrue(reservesFromDb[0].ReserveBills.Count == 1);
        }
        public void Can_Pay_Bill_From_Reserve()
        {
            // Arrange
            Reserve reserve = building.Reserve;
            decimal currentMoneyStatus = reserve.Money;

            LegalPerson legalPerson = new LegalPerson("12345678901", "Mile d.o.o.") {
                NumberOfBankAccount = "1234"
            };

            Bill bill = new Bill(legalPerson, building.Reserve, "opis plaćanja", 23);
            reserve.AddBillForPayment(bill);

            // Act
            reserve.PayBill(bill);

            // Assert
            Assert.AreEqual(currentMoneyStatus - bill.TotalAmountWithTax, reserve.Money);
            Assert.IsTrue(bill.IsPaid);
        }
        public void Can_Receive_Money_From_Payed_Bill()
        {
            // Arrange
            Reserve reserve = building.Reserve;
            decimal currentMoneyStatus = reserve.Money;
            var person = new PhysicalPerson("12345678903", "Mile", "Milic");

            Bill bill = new Bill(building.Reserve, person, "opis plaćanja", 23);
            var partitionSpace = building.LandRegistry.CreatePartitionSpace("123", 12m, "Opis", person);
            reserve.IssueReserveBillFor(partitionSpace, 23);

            // Act
            reserve.ReceivePaymentFor(bill);

            // Assert
            Assert.AreEqual(currentMoneyStatus + bill.TotalAmountWithTax, reserve.Money);
            Assert.IsTrue(bill.IsPaid);
        }
        public ActionResult IssueBill(int id, IssueBillModel model)
        {
            if (!User.IsInRole("buildingmanager")) { return new HttpUnauthorizedResult(); }

            LegalPerson legalPerson = personsRepository.GetLegalPersonByUsername(User.Identity.Name);
            var building = buildingsRepository.GetById(id);
            if (building == null) {
                return HttpNotFound();
            }

            if (!building.BuildingManager.LegalPerson.Equals(legalPerson)) {
                return new HttpUnauthorizedResult();
            }

            if (ModelState.IsValid) {
                try {
                    var bill = new Bill(legalPerson, building.Reserve, model.PaymentDescription, 23) {
                        ReferenceNumber = string.Format("{0}-{1}-{2}", building.Id, building.BuildingManager.Id, DateTime.Now.ToString("yyyy-MM-dd"))
                    };

                    foreach (var billItemModel in model.BillItems) {
                        var billItem = new BillItem(billItemModel.Quantity, billItemModel.Price, billItemModel.Description);
                        bill.AddBillItem(billItem);
                    }

                    billsRepository.SaveOrUpdate(bill);
                    var url = Url.Action("bill", "buildingmanager", new {Id = bill.Id}, "http");
                    emailNotifier.NotifyOfBilling(bill, url);
                    return RedirectToAction("bills");

                } catch (BusinessRulesException ex) {
                    ex.CopyTo(ModelState);
                }
            }

            model.Roles = Roles.GetRolesForUser();
            model.Building = Mapper.Map<Building, BuildingListModel>(building);

            return View(model);
        }
        private string generateGeneralInfoOfBill(Bill bill)
        {
            StringBuilder mailBodySb = new StringBuilder();
            mailBodySb.AppendFormat("Izdao: {0}", bill.From == null ? bill.BuildingName : bill.From.FullName).AppendLine();
            mailBodySb.AppendFormat("Za: {0}", bill.To == null ? bill.BuildingName : bill.To.FullName).AppendLine();
            mailBodySb.AppendFormat("Datum izdavanja računa: {0}", bill.DateTimeIssued.ToShortDateString()).AppendLine();
            if(bill.PaidDateTime.HasValue) {
                mailBodySb.AppendFormat("Datum plaćanja računa: {0}", bill.PaidDateTime.Value.ToShortDateString()).AppendLine();
            }
            mailBodySb.AppendFormat("Poziv na broj: {0}", bill.ReferenceNumber).AppendLine();
            mailBodySb.AppendLine().AppendLine();
            mailBodySb.AppendFormat("Osnovica za PDV: {0} kn", bill.TotalAmount).AppendLine();
            mailBodySb.AppendFormat("PDV: {0} kn", bill.TaxAmount).AppendLine();
            mailBodySb.AppendFormat("Ukupno: {0} kn", bill.TotalAmountWithTax).AppendLine();

            return mailBodySb.ToString();
        }
        /// <summary>
        /// Salje obavijest o uplati racuna
        /// </summary>
        /// <param name="bill">racun</param>
        /// <param name="url"></param>
        public void NotifyOfPaying(Bill bill, string url)
        {
            string mailSubject = "Plaćen račun: " + bill.Id;
            StringBuilder mailBodySb = new StringBuilder();
            mailBodySb.AppendFormat("Plaćen je račun br. {0}.", bill.Id).AppendLine();
            mailBodySb.AppendLine("----");
            mailBodySb.AppendLine(generateGeneralInfoOfBill(bill));
            mailBodySb.AppendLine();
            mailBodySb.AppendFormat("Detaljnije: {0}", url);

            string mailBody = mailBodySb.ToString();

            using (var smtpClient = new SmtpClient()) {
                Person person = bill.From == null ? bill.Reserve.Building.RepresentativeOfPartOwners : personsRepository.GetByOib(bill.From.Oib);
                string mailTo = housingMgmtUsersRepository.GetUserByPerson(person).Email;

                using (var mailMessage = new MailMessage(MAIL_FROM, mailTo)) {
                    using (var alternateView = AlternateView.CreateAlternateViewFromString(mailBody)) {
                        mailMessage.Subject = mailSubject;
                        alternateView.TransferEncoding = TransferEncoding.SevenBit;
                        mailMessage.AlternateViews.Add(alternateView);
                        smtpClient.Send(mailMessage);
                    }
                }

            }
        }
 /// <summary>
 /// Dodaje račun za naplatu
 /// </summary>
 /// <param name="bill">racun za naplatu</param>
 public virtual void AddBillForPayment(Bill bill)
 {
     // moguce je dodati samo one racune koje je izdala pravna osoba
     if(bill.From != null && bill.Reserve != null) {
         reserveBills.Add(bill);
     } else {
         throw new BusinessRulesException("Za naplaćivanje računa iz pričuve moguće je dodati samo račune izdane od strane pravne osobe.");
     }
 }
 /// <summary>
 /// Uplata novca dobivenog iz pricuve
 /// </summary>
 /// <param name="bill">racun</param>
 public virtual void ReceivePaymentFor(Bill bill)
 {
     // moze se samo naplatiti pricuva iz racuna za pricuvu, odnosno ako ga je izdala zgrada
     if (bill.Reserve != null && bill.To != null) {
         bill.SetPaid();
         money += bill.TotalAmountWithTax;
     } else {
         var businessEx = new BusinessRulesException<Reserve>();
         businessEx.AddErrorForModel("Nije moguce naplatiti pričuvu iz računa koji nije račun za pričuvu.");
     }
 }
        /// <summary>
        /// Placanje racuna iz pricuve
        /// </summary>
        /// <param name="bill">racun</param>
        /// <returns></returns>
        public virtual bool PayBill(Bill bill)
        {
            var unpaidBills = GetUnpaidBills();
            if(!unpaidBills.Contains(bill)) {
                throw new BusinessRulesException("Navedeni račun nije za naplatu pričuvom zgrade.");
            }

            if (money < bill.TotalAmountWithTax) {
                return false;
            }

            money -= bill.TotalAmountWithTax;
            bill.SetPaid();

            return true;
        }
        /// <summary>
        /// Izadaje racun za pricuvu
        /// </summary>
        /// <param name="partitionSpace">stan za kojieg se izdaje racun za placanje pricuve</param>
        /// <param name="tax">porez</param>
        /// <returns>racun za pricuvu</returns>
        public virtual void IssueReserveBillFor(IPartitionSpace partitionSpace, short tax)
        {
            if (partitionSpace.Owner == null) { throw new BusinessRulesException("Owner doesn't exist."); }
            if(!building.LandRegistry.PartitionSpaces.Contains(partitionSpace)) {
                throw new BusinessRulesException("Etaža ne pripada ovoj zgradi, onodno pričuvi.");
            }

            StringBuilder paymentDescriptionSb = new StringBuilder();
            paymentDescriptionSb.AppendLine(string.Format("Račun mjesečne pričuve za zgradu {0}.", building.Address));
            paymentDescriptionSb.AppendLine(string.Format("Temeljem stana broj uloška: {0}", partitionSpace.RegistryNumber));
            paymentDescriptionSb.AppendLine(string.Format("Površine {0}, i koeficijenta pričuve {1}.", partitionSpace.SurfaceArea, building.ReserveCoefficient));

            Bill bill = new Bill(this, partitionSpace.Owner, paymentDescriptionSb.ToString(), tax);
            decimal price = building.ReserveCoefficient * partitionSpace.SurfaceArea;
            BillItem billItem = new BillItem(1, price, "Mjesečna naknada za pričuvu");
            bill.AddBillItem(billItem);
            bill.ReferenceNumber = string.Format("{0}-{1}-{2}", REFERENCE_NUMBER_PREFIX, partitionSpace.Id, bill.DateTimeIssued.ToString("yyyy-MM-dd"));

            reserveBills.Add(bill);
        }
        public virtual void SetBill(Bill bill)
        {
            var errors = new BusinessRulesException<Maintenance>();

            if(bill.From.Oib != contractor.Oib) {
                errors.AddErrorFor(m => m.Bill,
                    "Constractor who issued bill isn't the same as contractor responsible for the maintenance.");
            }

            if(errors.Errors.Any()) {
                throw errors;
            }

            this.bill = bill;
        }
        public ActionResult IssueBill(IssueBillModel model)
        {
            if (!User.IsInRole("contractor")) { return new HttpUnauthorizedResult(); }

            LegalPerson legalPerson = personsRepository.GetLegalPersonByUsername(User.Identity.Name);

            if(ModelState.IsValid) {
                var maintenance = maintenancesRepository.GetById(model.UnbilledMaintance);
                if(maintenance != null) {
                    try {
                        var bill = new Bill(legalPerson, maintenance.Building.Reserve, model.PaymentDescription, 23) {
                            ReferenceNumber = string.Format("{0}-{1}-{2}", maintenance.Building.Id, maintenance.Id, DateTime.Now.ToString("yyyy-MM-dd"))
                        };
                        foreach (var billItemModel in model.BillItems) {
                            var billItem = new BillItem(billItemModel.Quantity, billItemModel.Price, billItemModel.Description);
                            bill.AddBillItem(billItem);
                        }

                        maintenance.SetBill(bill);
                        billsRepository.SaveOrUpdate(bill);

                        var url = Url.Action("bill", "contractor", new {Id = bill.Id}, "http");
                        emailNotifier.NotifyOfBilling(bill, url);
                        return RedirectToAction("bills");

                    } catch(BusinessRulesException ex) {
                        ex.CopyTo(ModelState);
                    }

                } else {
                    ModelState.AddModelError("UnbilledMaintance", "Odabrali ste ne postojeće održavanje/popravak.");
                }
            }

            var maintenances = maintenancesRepository.GetAllMaintenancesWithNoBillByContractor(legalPerson);
            var mappedMaintenances = Mapper.Map<IEnumerable<Maintenance>, IEnumerable<MaintenanceDetailModel>>(maintenances);
            model.UnbilledMaintances = new SelectList(mappedMaintenances, "Id", "MaintenanceRequest.Subject");
            model.Roles = Roles.GetRolesForUser();

            return View(model);
        }