diff --git a/Package.swift b/Package.swift index 6eb07f65..1041d827 100644 --- a/Package.swift +++ b/Package.swift @@ -84,7 +84,7 @@ let package = Package( .target(name: "TIAuth", dependencies: ["TIFoundationUtils"], path: "TIAuth/Sources"), //MARK: - Skolkovo - .target(name: "TIEcommerce", path: "TIEcommerce/Sources"), + .target(name: "TIEcommerce", dependencies: ["TIFoundationUtils"], path: "TIEcommerce/Sources"), // MARK: - Tests diff --git a/TIEcommerce/Sources/Cart protocols/Receipt.swift b/TIEcommerce/Sources/Cart protocols/Receipt.swift new file mode 100644 index 00000000..65b42365 --- /dev/null +++ b/TIEcommerce/Sources/Cart protocols/Receipt.swift @@ -0,0 +1,41 @@ +import Foundation + +///Предварительный расчёт стоимости товаров +/// +///В интерфейсе модели товара должна присуствовать текущая цена исходя из которой можно рассчитать итоговую стоимость всей корзины +protocol ProductPriceHolder { + ///Цена в определённой валюте + var price: CartProductPrice { get } +} + +///Применение промокодов +/// +///В интерфейсе локальной корзины должна присуствовать возможность применения или удаления промокода. Промокодов в корзине может быть несколько. У промокода должно присутсвовать опциональное поле discount, для расчёта скидки в сумме чека. +protocol PromocodesHolder { + var promocodes: [Promocode] { get set } +} + +protocol Promocode { + var discount: CartProductPrice? { get } +} + +///Расчёт бонусов +/// +///В интерфейсе товара должно присуствовать опциональное поле бонусов, которое будет суммироваться для отображения в чеке. +protocol BonusesHolder { + ///Количество бонусов, которые будут начислены при покупке + var bonuses: Int? { get } +} + +///В интерфейсе серверной корзины должно присуствовать опциональное поле с количеством доступных бонусов для использования. +protocol AvailableBonusesHolder { + ///Количество доступных бонусов для использования + var availableBonuses: Int? { get } +} + +///Товары не доступные для заказа +/// +///По аналогии с удалёнными товарами из корзины, товары не доступные для заказа не должны попадать на стадию оформления заказа и не должны расчиываться в общей сумме корзины +protocol NotAvailableProductsHolder { + var notAvailableProducts: [CartProduct] { get set } +} diff --git a/TIEcommerce/Sources/Classes/CartService.swift b/TIEcommerce/Sources/Classes/CartService.swift new file mode 100644 index 00000000..d33df149 --- /dev/null +++ b/TIEcommerce/Sources/Classes/CartService.swift @@ -0,0 +1,38 @@ +// +// Copyright (c) 2022 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation +import TIFoundationUtils + +protocol CartPublisher { + func subscribeOnCartChanging(completion: ParameterClosure)) -> Cancellable + func subscribeOnProductChanging(productId: Int, completion: ParameterClosure) -> Cancellable +} + +open class CartService: RemovableProductCart, NotAvailableProductsHolder, PromocodesHolder { + open private(set) var localCart: Cart? + open private(set) var removedProducts: [CartProduct] + open private(set) var notAvailableProducts: [CartProduct] + open private(set) var promocodes: [Promocode] + + open func updateCountInCart(for product: CartProduct, count: Int) { } + open func updateCountInCart(for productId: Int, count: Int) { } +} diff --git a/TIEcommerce/Sources/Classes/IgnoringErrorsRepeatClosure.swift b/TIEcommerce/Sources/Classes/IgnoringErrorsRepeatClosure.swift index 8dc92f4d..59e234de 100644 --- a/TIEcommerce/Sources/Classes/IgnoringErrorsRepeatClosure.swift +++ b/TIEcommerce/Sources/Classes/IgnoringErrorsRepeatClosure.swift @@ -5,6 +5,11 @@ class IgnoringErrorsRepeatClosure { private(set) var numberOfAttempts: Int private var ignoringErrors: Set + /* + немного не так, должен быть метод который принимает BaseErrorResponse и associatedType NetworkError и возвращает true если можно попробовать повторить + + ну и closure с запросом в ответ возвращает EndpointErrorResult из TINetworking + */ init(ignoringErrors: Set = [], numberOfAttempts: Int) { self.ignoringErrors = ignoringErrors self.numberOfAttempts = numberOfAttempts diff --git a/TIEcommerce/Sources/Models/CartProduct.swift b/TIEcommerce/Sources/Models/CartProduct.swift index 98f7b251..da6d3113 100644 --- a/TIEcommerce/Sources/Models/CartProduct.swift +++ b/TIEcommerce/Sources/Models/CartProduct.swift @@ -1,6 +1,6 @@ import Foundation -protocol CartProduct { +protocol CartProduct: ProductPriceHolder, BonusesHolder { ///Идентификатор продукта var id: String { get } ///Цена в определённой валюте