From cddae04f2eab090d212bbd6dcde5e10ff85b92f9 Mon Sep 17 00:00:00 2001 From: Grigory Boyko Date: Fri, 29 Jul 2022 21:08:11 +0700 Subject: [PATCH] feat: Add initial files for Cart module --- Package.swift | 6 +++++ .../Sources/Cart protocols/CartSyncable.swift | 25 +++++++++++++++++++ .../Cart protocols/CartUpdatable.swift | 9 +++++++ .../Classes/IgnoringErrorsRepeatClosure.swift | 23 +++++++++++++++++ .../Models/BaseErrorResponseBody.swift | 8 ++++++ TIEcommerce/Sources/Models/Cart.swift | 10 ++++++++ TIEcommerce/Sources/Models/CartProduct.swift | 14 +++++++++++ .../Sources/Models/CartProductPrice.swift | 8 ++++++ TIEcommerce/TIEcommerce.podspec | 16 ++++++++++++ 9 files changed, 119 insertions(+) create mode 100644 TIEcommerce/Sources/Cart protocols/CartSyncable.swift create mode 100644 TIEcommerce/Sources/Cart protocols/CartUpdatable.swift create mode 100644 TIEcommerce/Sources/Classes/IgnoringErrorsRepeatClosure.swift create mode 100644 TIEcommerce/Sources/Models/BaseErrorResponseBody.swift create mode 100644 TIEcommerce/Sources/Models/Cart.swift create mode 100644 TIEcommerce/Sources/Models/CartProduct.swift create mode 100644 TIEcommerce/Sources/Models/CartProductPrice.swift create mode 100644 TIEcommerce/TIEcommerce.podspec diff --git a/Package.swift b/Package.swift index 5a2f0396..cff7e790 100644 --- a/Package.swift +++ b/Package.swift @@ -37,6 +37,9 @@ let package = Package( .library(name: "TITransitions", targets: ["TITransitions"]), .library(name: "TIPagination", targets: ["TIPagination"]), .library(name: "TIAuth", targets: ["TIAuth"]), + + //MARK: - Skolkovo + .library(name: "TIEcommerce", targets: ["TIEcommerce"]) ], dependencies: [ .package(url: "https://github.com/maxsokolov/TableKit.git", .upToNextMajor(from: "2.11.0")), @@ -80,6 +83,9 @@ let package = Package( .target(name: "TIPagination", dependencies: ["Cursors", "TISwiftUtils"], path: "TIPagination/Sources"), .target(name: "TIAuth", dependencies: ["TIFoundationUtils"], path: "TIAuth/Sources"), + //MARK: - Skolkovo + .target(name: "TIEcommerce", dependencies: ["TIEcommerce"], path: "TIEcommerce/Sources"), + // MARK: - Tests .testTarget( diff --git a/TIEcommerce/Sources/Cart protocols/CartSyncable.swift b/TIEcommerce/Sources/Cart protocols/CartSyncable.swift new file mode 100644 index 00000000..f0a41232 --- /dev/null +++ b/TIEcommerce/Sources/Cart protocols/CartSyncable.swift @@ -0,0 +1,25 @@ +import Foundation + +///Содержит абстрактный метод, позволяющий получить на выходе итоговую локальную корзину. Должен поддерживать две стратегии работы: +///- замена локальной корзины серверной `func replace(localCart:, with:) -> CartModelProtocol` +///- слияние локальной корзины с серверной (детали слияния определяются в проекте) `func merge(localCart:, remoteCart:) -> CartModelProtocol` +protocol CartSyncable { + /** + Cлияние локальной корзины с серверной + - Parameters: + - localCart: `Cart` – локальная корзина + - remoteCart: `Cart` – серверная корзина + - Returns: `Cart` – совмещенная корзина + */ + func merge(localCart: Cart, + remoteCart: Cart) -> Cart + /** + Замена локальной корзины серверной + - Parameters: + - localCart: `Cart` – локальная корзина + - remoteCart: `Cart` – серверная корзина + - Returns: `Cart` – серверная корзина + */ + func replace(localCart: Cart, + with remoteCart: Cart) -> Cart +} diff --git a/TIEcommerce/Sources/Cart protocols/CartUpdatable.swift b/TIEcommerce/Sources/Cart protocols/CartUpdatable.swift new file mode 100644 index 00000000..78c8ad2b --- /dev/null +++ b/TIEcommerce/Sources/Cart protocols/CartUpdatable.swift @@ -0,0 +1,9 @@ +import Foundation + +///Содержит абстрактный метод, позволяющий отправить локальную корзину полностью и получить в ответ серверную корзину +protocol CartUpdatable { + ///Отправляем локальную корзину полностью и получаем в ответ серверную корзину или ошибку + func loadRemoteCart(from localCart: Cart, + successCompletion: ParameterClosure?, + failureCompletion: ParameterClosure?) +} diff --git a/TIEcommerce/Sources/Classes/IgnoringErrorsRepeatClosure.swift b/TIEcommerce/Sources/Classes/IgnoringErrorsRepeatClosure.swift new file mode 100644 index 00000000..8dc92f4d --- /dev/null +++ b/TIEcommerce/Sources/Classes/IgnoringErrorsRepeatClosure.swift @@ -0,0 +1,23 @@ +import Foundation + +///При получении ошибки из `gnoringErrors` повторение отправки до `numberOfAttempts` раз +class IgnoringErrorsRepeatClosure { + private(set) var numberOfAttempts: Int + private var ignoringErrors: Set + + init(ignoringErrors: Set = [], numberOfAttempts: Int) { + self.ignoringErrors = ignoringErrors + self.numberOfAttempts = numberOfAttempts + } + + func performIfNeeded(with error: BaseErrorResponseBody, + repeatClosure: VoidClosure, + errorCompletion: ParameterClosure?) { + if ignoringErrors.contains(error) && numberOfAttempts > 0 { + numberOfAttempts -= 1 + repeatClosure() + } else { + errorCompletion?(error) + } + } +} diff --git a/TIEcommerce/Sources/Models/BaseErrorResponseBody.swift b/TIEcommerce/Sources/Models/BaseErrorResponseBody.swift new file mode 100644 index 00000000..0ecf98c0 --- /dev/null +++ b/TIEcommerce/Sources/Models/BaseErrorResponseBody.swift @@ -0,0 +1,8 @@ +import Foundation + +struct BaseErrorResponseBody: Decodable, Equatable, Hashable { + ///Код ошибки + let errorCode: Int + ///Текст сообщения об ошибке + let errorMessage: String +} diff --git a/TIEcommerce/Sources/Models/Cart.swift b/TIEcommerce/Sources/Models/Cart.swift new file mode 100644 index 00000000..3e67416e --- /dev/null +++ b/TIEcommerce/Sources/Models/Cart.swift @@ -0,0 +1,10 @@ +import Foundation + +protocol Cart { + ///Продукты в корзине пользователя + var products: [CartProduct] { get } + ///Применённые промокоды + var promocodes: [String] { get } + ///Количество доступных бонусов для использования + var availableBonuses: Int? { get } +} diff --git a/TIEcommerce/Sources/Models/CartProduct.swift b/TIEcommerce/Sources/Models/CartProduct.swift new file mode 100644 index 00000000..98f7b251 --- /dev/null +++ b/TIEcommerce/Sources/Models/CartProduct.swift @@ -0,0 +1,14 @@ +import Foundation + +protocol CartProduct { + ///Идентификатор продукта + var id: String { get } + ///Цена в определённой валюте + var price: CartProductPrice { get } + ///Сколько единиц есть доступно + var availableCount: Int? { get } + ///Варианты товара (фасовка, цвет, размер, и т.п.) + var variants: [CartProduct?] { get } + ///Количество бонусов, которые будут начислены при покупке + var bonuses: Int? { get } +} diff --git a/TIEcommerce/Sources/Models/CartProductPrice.swift b/TIEcommerce/Sources/Models/CartProductPrice.swift new file mode 100644 index 00000000..5047b728 --- /dev/null +++ b/TIEcommerce/Sources/Models/CartProductPrice.swift @@ -0,0 +1,8 @@ +import Foundation + +protocol CartProductPrice { + ///Стоимость + var value: Int { get } + ///Трехсимвольный код валюты в ISO 4217 + var currencyCode: String { get } +} diff --git a/TIEcommerce/TIEcommerce.podspec b/TIEcommerce/TIEcommerce.podspec new file mode 100644 index 00000000..fcbb0d88 --- /dev/null +++ b/TIEcommerce/TIEcommerce.podspec @@ -0,0 +1,16 @@ +Pod::Spec.new do |s| + s.name = 'TIEcommerce' + s.version = '1.25.0' + s.summary = 'Cart' + s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name + s.license = { :type => 'MIT', :file => 'LICENSE' } + s.author = { 'petropavel13' => 'ivan.smolin@touchin.ru' } + s.source = { :git => 'https://github.com/TouchInstinct/LeadKit.git', :tag => s.version.to_s } + + s.ios.deployment_target = '13.0' + s.swift_versions = ['5.3'] + + s.source_files = s.name + '/Sources/**/*' + + s.dependency 'TIFoundationUtils', s.version.to_s +end