예제 #1
0
        /// <summary>
        /// Fetches a Material from the MaterialRepository given its ID.
        /// </summary>
        /// <param name = "materialID">the Material's ID</param>
        /// <returns>DTO that represents the Material</returns>
        public MaterialDTO findMaterialByID(long materialID, bool pricedFinishesOnly)
        {
            Material material = PersistenceContext.repositories().createMaterialRepository().find(materialID);

            if (material == null)
            {
                throw new ResourceNotFoundException(ERROR_MATERIAL_NOT_FOUND);
            }

            if (pricedFinishesOnly)
            {
                FinishPriceTableRepository finishPriceTableRepository =
                    PersistenceContext.repositories().createFinishPriceTableRepository();
                List <Finish> pricedFinishes = new List <Finish>();
                foreach (Finish finish in material.Finishes)
                {
                    if (finishPriceTableRepository.fetchCurrentMaterialFinishPrice(finish.Id) != null)
                    {
                        pricedFinishes.Add(finish);
                    }
                }

                if (pricedFinishes.Count == 0)
                {
                    throw new ResourceNotFoundException(NO_PRICED_FINISHES);
                }

                material.Finishes.Clear();
                material.Finishes.AddRange(pricedFinishes);
                return(material.toDTO());
            }

            return(PersistenceContext.repositories().createMaterialRepository().find(materialID).toDTO());
        }
예제 #2
0
        /// <summary>
        /// Checks if a material finish from a customized product has a current price
        /// </summary>
        /// <param name="finishPriceTableRepository">Finish Price Table Repository</param>
        /// <param name="finishId">Finish's PID</param>
        /// <returns>FinishPriceTableEntry with the finish's current price</returns>
        private static FinishPriceTableEntry getCurrentFinishPrice(FinishPriceTableRepository finishPriceTableRepository, long finishId)
        {
            FinishPriceTableEntry finishPriceTableEntry =
                finishPriceTableRepository.fetchCurrentMaterialFinishPrice(finishId);

            if (finishPriceTableEntry == null)
            {
                throw new ResourceNotFoundException
                      (
                          string.Format(FINISH_HAS_NO_CURRENT_PRICE, finishId)
                      );
            }

            return(finishPriceTableEntry);
        }
예제 #3
0
        /// <summary>
        /// Calculates the price
        /// </summary>
        /// <param name="fetchCustomizedProductPrice">FetchCustomizedProductModelView with the necessary information to fetch the customized product's price</param>
        /// <returns>CustomizedProductPriceModelView with the price of the customized product</returns>
        public static async Task <CustomizedProductFinalPriceModelView> calculatePrice(FetchCustomizedProductPriceModelView fetchCustomizedProductPrice, IHttpClientFactory clientFactory)
        {
            if (fetchCustomizedProductPrice.currency != null)
            {
                CurrenciesService.checkCurrencySupport(fetchCustomizedProductPrice.currency);
            }

            if (fetchCustomizedProductPrice.area != null)
            {
                AreasService.checkAreaSupport(fetchCustomizedProductPrice.area);
            }

            CustomizedProduct customizedProduct =
                PersistenceContext.repositories().createCustomizedProductRepository().find(fetchCustomizedProductPrice.id);

            if (customizedProduct == null)
            {
                throw new ResourceNotFoundException
                      (
                          string.Format(CUSTOMIZED_PRODUCT_NOT_FOUND, fetchCustomizedProductPrice.id)
                      );
            }

            if (customizedProduct.status == CustomizationStatus.PENDING)
            {
                throw new ArgumentException
                      (
                          CUSTOMIZED_PRODUCT_NOT_FINISHED
                      );
            }

            //TODO Should the fetching of prices of customized products that aren't base products be allowed?

            MaterialPriceTableRepository materialPriceTableRepository =
                PersistenceContext.repositories().createMaterialPriceTableRepository();
            FinishPriceTableRepository finishPriceTableRepository =
                PersistenceContext.repositories().createFinishPriceTableRepository();

            CustomizedProductFinalPriceModelView   customizedProductTotalPrice = new CustomizedProductFinalPriceModelView();
            List <CustomizedProductPriceModelView> customizedProductPriceList  = new List <CustomizedProductPriceModelView>();

            MaterialPriceTableEntry materialPriceTableEntry =
                getCurrentMaterialPrice(materialPriceTableRepository, customizedProduct.customizedMaterial.material.Id);

            FinishPriceTableEntry finishPriceTableEntry = null;

            if (customizedProduct.customizedMaterial.finish != null)
            {
                finishPriceTableEntry = getCurrentFinishPrice(finishPriceTableRepository,
                                                              customizedProduct.customizedMaterial.material.Finishes.Where(f => f.Equals(customizedProduct.customizedMaterial.finish)).SingleOrDefault().Id);
            }

            //TODO What should we do about doors?
            //TODO Should we consider that every component has a box geometry?
            //!For now the surface area of every product is being calculated as if it the product was a SIX FACED RIGHT RECTANGULAR PRISM

            CustomizedProductPriceModelView parentCustomizedProductModelView =
                await buildCustomizedProductPriceModelView(customizedProduct, fetchCustomizedProductPrice, materialPriceTableEntry, finishPriceTableEntry, clientFactory);

            customizedProductPriceList.Add(parentCustomizedProductModelView);

            if (customizedProduct.hasCustomizedProducts())
            {
                List <CustomizedProductPriceModelView> childCustomizedProducts = new List <CustomizedProductPriceModelView>();
                customizedProductPriceList.AddRange(await
                                                    calculatePricesOfChildCustomizedProducts(childCustomizedProducts, customizedProduct, fetchCustomizedProductPrice,
                                                                                             materialPriceTableRepository, finishPriceTableRepository, clientFactory));
            }

            customizedProductTotalPrice.customizedProducts = customizedProductPriceList;
            customizedProductTotalPrice.finalPrice         = calculateFinalPriceOfCustomizedProduct(customizedProductTotalPrice, fetchCustomizedProductPrice);

            return(customizedProductTotalPrice);
        }
예제 #4
0
        /// <summary>
        /// Calculates the price of all child customized products of a given customized product
        /// </summary>
        /// <param name="customizedProduct">Parent Customized Product</param>
        /// <param name="fetchCustomizedProductPrice">Information about currency/area conversion</param>
        /// <param name="materialPriceTableRepository">MaterialPriceTableRepository instance to fetch current material prices</param>
        /// <param name="finishPriceTableRepository">FinishPriceTableRepository instance to fetch current finish prices</param>
        /// <param name="clientFactory">Injected HTTP Client Factory</param>
        /// <returns>IEnumerable containing the prices of all child customized products</returns>
        private static async Task <IEnumerable <CustomizedProductPriceModelView> > calculatePricesOfChildCustomizedProducts(List <CustomizedProductPriceModelView> childCustomizedProductPrices, CustomizedProduct customizedProduct, FetchCustomizedProductPriceModelView fetchCustomizedProductPrice,
                                                                                                                            MaterialPriceTableRepository materialPriceTableRepository, FinishPriceTableRepository finishPriceTableRepository, IHttpClientFactory clientFactory)
        {
            foreach (Slot slot in customizedProduct.slots)
            {
                foreach (CustomizedProduct childCustomizedProduct in slot.customizedProducts)
                {
                    MaterialPriceTableEntry materialPriceTableEntry =
                        getCurrentMaterialPrice(materialPriceTableRepository, childCustomizedProduct.customizedMaterial.material.Id);

                    FinishPriceTableEntry finishPriceTableEntry = null;

                    if (childCustomizedProduct.customizedMaterial.finish != null)
                    {
                        finishPriceTableEntry = getCurrentFinishPrice(finishPriceTableRepository,
                                                                      childCustomizedProduct.customizedMaterial.material.Finishes.Where(f => f.Equals(childCustomizedProduct.customizedMaterial.finish)).SingleOrDefault().Id);
                    }

                    CustomizedProductPriceModelView childCustomizedProductPriceModelView =
                        await buildCustomizedProductPriceModelView(childCustomizedProduct, fetchCustomizedProductPrice,
                                                                   materialPriceTableEntry, finishPriceTableEntry, clientFactory);

                    childCustomizedProductPrices.Add(childCustomizedProductPriceModelView);

                    if (childCustomizedProduct.hasCustomizedProducts())
                    {
                        await calculatePricesOfChildCustomizedProducts(childCustomizedProductPrices, childCustomizedProduct,
                                                                       fetchCustomizedProductPrice, materialPriceTableRepository, finishPriceTableRepository, clientFactory);
                    }
                }
            }

            return(childCustomizedProductPrices);
        }
        /// <summary>
        /// Updates a finish's price table entry
        /// </summary>
        /// <param name="modelView">model view containing updatable information</param>
        /// <returns>True if the update is successful</returns>
        public static GetMaterialFinishPriceModelView update(UpdateFinishPriceTableEntryModelView modelView, IHttpClientFactory clientFactory)
        {
            string             defaultCurrency    = CurrencyPerAreaConversionService.getBaseCurrency();
            string             defaultArea        = CurrencyPerAreaConversionService.getBaseArea();
            MaterialRepository materialRepository = PersistenceContext.repositories().createMaterialRepository();
            long materialId = modelView.entityId;

            bool performedAtLeastOneUpdate = false;

            Material material = materialRepository.find(materialId);

            if (material == null)
            {
                throw new ResourceNotFoundException(MATERIAL_NOT_FOUND);
            }

            foreach (Finish finish in material.Finishes)
            {
                if (finish.Id == modelView.finishId)
                {
                    FinishPriceTableRepository finishPriceTableRepository = PersistenceContext.repositories().createFinishPriceTableRepository();
                    long finishPriceTableEntryId = modelView.tableEntryId;

                    FinishPriceTableEntry tableEntryToUpdate = finishPriceTableRepository.find(finishPriceTableEntryId);

                    if (tableEntryToUpdate == null)
                    {
                        throw new ResourceNotFoundException(ENTRY_NOT_FOUND);
                    }

                    if (tableEntryToUpdate.entity.Id != modelView.finishId)
                    {
                        throw new InvalidOperationException(ENTRY_DOESNT_BELONG_TO_FINISH);
                    }

                    LocalDateTime currentTime = NodaTime.LocalDateTime.FromDateTime(SystemClock.Instance.GetCurrentInstant().ToDateTimeUtc());

                    if (modelView.priceTableEntry.startingDate != null && LocalDateTimePattern.GeneralIso.Format(tableEntryToUpdate.timePeriod.startingDate).Equals(modelView.priceTableEntry.startingDate))
                    {
                        if (tableEntryToUpdate.timePeriod.startingDate.CompareTo(currentTime) < 0)
                        {
                            throw new InvalidOperationException(PAST_DATE);
                        }
                    }

                    if (modelView.priceTableEntry.endingDate != null && LocalDateTimePattern.GeneralIso.Format(tableEntryToUpdate.timePeriod.endingDate).Equals(modelView.priceTableEntry.endingDate))
                    {
                        if (tableEntryToUpdate.timePeriod.endingDate.CompareTo(currentTime) < 0)
                        {
                            throw new InvalidOperationException(PAST_DATE);
                        }
                    }

                    if (modelView.priceTableEntry.price != null)
                    {
                        CurrenciesService.checkCurrencySupport(modelView.priceTableEntry.price.currency);
                        AreasService.checkAreaSupport(modelView.priceTableEntry.price.area);

                        Price newPrice = null;
                        try
                        {
                            if (defaultCurrency.Equals(modelView.priceTableEntry.price.currency) && defaultArea.Equals(modelView.priceTableEntry.price.area))
                            {
                                newPrice = Price.valueOf(modelView.priceTableEntry.price.value);
                            }
                            else
                            {
                                Task <double> convertedValueTask = new CurrencyPerAreaConversionService(clientFactory)
                                                                   .convertCurrencyPerAreaToDefaultCurrencyPerArea(
                                    modelView.priceTableEntry.price.currency,
                                    modelView.priceTableEntry.price.area,
                                    modelView.priceTableEntry.price.value);
                                convertedValueTask.Wait();
                                double convertedValue = convertedValueTask.Result;
                                newPrice = Price.valueOf(convertedValue);
                            }
                        }
                        catch (HttpRequestException)
                        {
                            newPrice = Price.valueOf(modelView.priceTableEntry.price.value);
                        }

                        tableEntryToUpdate.changePrice(newPrice);
                        performedAtLeastOneUpdate = true;
                    }

                    if (modelView.priceTableEntry.endingDate != null)
                    {
                        LocalDateTime newEndingDate;
                        try
                        {
                            string newEndingDateAsString = modelView.priceTableEntry.endingDate;
                            newEndingDate = LocalDateTimePattern.GeneralIso.Parse(newEndingDateAsString).GetValueOrThrow();
                            tableEntryToUpdate.changeTimePeriod(TimePeriod.valueOf(tableEntryToUpdate.timePeriod.startingDate, newEndingDate));
                            performedAtLeastOneUpdate = true;
                        }
                        catch (UnparsableValueException)
                        {
                            throw new UnparsableValueException(DATES_WRONG_FORMAT + LocalDateTimePattern.GeneralIso.PatternText);
                        }
                    }

                    if (modelView.priceTableEntry.startingDate != null)
                    {
                        LocalDateTime newStartingDate;
                        try
                        {
                            string newStartingDateAsString = modelView.priceTableEntry.startingDate;
                            newStartingDate = LocalDateTimePattern.GeneralIso.Parse(newStartingDateAsString).GetValueOrThrow();
                            tableEntryToUpdate.changeTimePeriod(TimePeriod.valueOf(newStartingDate, tableEntryToUpdate.timePeriod.endingDate));
                            performedAtLeastOneUpdate = true;
                        }
                        catch (UnparsableValueException)
                        {
                            throw new UnparsableValueException(DATES_WRONG_FORMAT + LocalDateTimePattern.GeneralIso.PatternText);
                        }
                    }

                    if (performedAtLeastOneUpdate)
                    {
                        FinishPriceTableEntry updatedTableEntry = finishPriceTableRepository.update(tableEntryToUpdate);

                        if (updatedTableEntry == null)
                        {
                            throw new InvalidOperationException(UPDATE_NOT_SUCCESSFUL);
                        }

                        GetMaterialFinishPriceModelView updatedTableEntryModelView = new GetMaterialFinishPriceModelView();

                        updatedTableEntryModelView.id           = updatedTableEntry.Id;
                        updatedTableEntryModelView.finishId     = updatedTableEntry.entity.Id;
                        updatedTableEntryModelView.value        = updatedTableEntry.price.value;
                        updatedTableEntryModelView.currency     = defaultCurrency;
                        updatedTableEntryModelView.area         = defaultArea;
                        updatedTableEntryModelView.startingDate = LocalDateTimePattern.GeneralIso.Format(updatedTableEntry.timePeriod.startingDate);
                        updatedTableEntryModelView.endingDate   = LocalDateTimePattern.GeneralIso.Format(updatedTableEntry.timePeriod.endingDate);

                        return(updatedTableEntryModelView);
                    }
                }
            }
            throw new ResourceNotFoundException(FINISH_NOT_FOUND_OR_DOESNT_BELONG_TO_MATERIAL);
        }
 /// <summary>
 /// Constructor with injected type of repositories
 /// </summary>
 /// <param name="materialPriceTableRepository">material price table repository</param>
 /// <param name="finishPriceTableRepository">finish price table repository</param>
 public PriceTablesController(MaterialPriceTableRepository materialPriceTableRepository, FinishPriceTableRepository finishPriceTableRepository, IHttpClientFactory clientFactory)
 {
     this.materialPriceTableRepository = materialPriceTableRepository;
     this.finishPriceTableRepository   = finishPriceTableRepository;
     this.clientFactory = clientFactory;
 }