Updated on 2026-08-14
This commit is contained in:
parent
5c293e71ec
commit
6caeea3576
22 changed files with 243 additions and 135 deletions
|
|
@ -38,6 +38,7 @@ data class CustomerMeResponse(
|
||||||
@Json(name = "id") val id: String?,
|
@Json(name = "id") val id: String?,
|
||||||
@Json(name = "type") val type: String?,
|
@Json(name = "type") val type: String?,
|
||||||
@Json(name = "name") val name: String?,
|
@Json(name = "name") val name: String?,
|
||||||
|
@Json(name = "program_name") val programName: String?,
|
||||||
@Json(name = "description_items") val descriptionItems: List<DescriptionItem>?,
|
@Json(name = "description_items") val descriptionItems: List<DescriptionItem>?,
|
||||||
@Json(name = "images") val images: List<Image>? = null,
|
@Json(name = "images") val images: List<Image>? = null,
|
||||||
@Json(name = "fees") val fees: List<Fee>? = null,
|
@Json(name = "fees") val fees: List<Fee>? = null,
|
||||||
|
|
|
||||||
|
|
@ -98,15 +98,22 @@
|
||||||
<string name="address_book_add_address">Agregar dirección</string>
|
<string name="address_book_add_address">Agregar dirección</string>
|
||||||
<string name="address_book_add_address_description">Agregue la dirección y seleccione la red</string>
|
<string name="address_book_add_address_description">Agregue la dirección y seleccione la red</string>
|
||||||
<string name="address_book_add_contact">Añadir contacto</string>
|
<string name="address_book_add_contact">Añadir contacto</string>
|
||||||
|
<string name="address_book_address_copied">Dirección copiada</string>
|
||||||
|
<string name="address_book_address_taken_error">Esta dirección ya está guardada como %1$s</string>
|
||||||
<plurals name="address_book_addresses">
|
<plurals name="address_book_addresses">
|
||||||
<item quantity="one">%d dirección</item>
|
<item quantity="one">%d dirección</item>
|
||||||
<item quantity="other">%d direcciones</item>
|
<item quantity="other">%d direcciones</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<string name="address_book_choose_address">Seleccione una dirección</string>
|
||||||
|
<string name="address_book_clear_all_networks">Borrar todo</string>
|
||||||
<string name="address_book_contact">Contacto</string>
|
<string name="address_book_contact">Contacto</string>
|
||||||
<string name="address_book_contact_name">Nombre de contacto</string>
|
<string name="address_book_contact_name">Nombre de contacto</string>
|
||||||
<string name="address_book_copy_address">Copiar dirección</string>
|
<string name="address_book_copy_address">Copiar dirección</string>
|
||||||
|
<string name="address_book_create_success_message">Contacto guardado</string>
|
||||||
<string name="address_book_creating_error">No se pudo crear el contacto. Inténtelo de nuevo más tarde.</string>
|
<string name="address_book_creating_error">No se pudo crear el contacto. Inténtelo de nuevo más tarde.</string>
|
||||||
|
<string name="address_book_delete_contact">Eliminar contacto</string>
|
||||||
<string name="address_book_delete_contact_description">Este contacto se eliminará de todas sus libretas de direcciones</string>
|
<string name="address_book_delete_contact_description">Este contacto se eliminará de todas sus libretas de direcciones</string>
|
||||||
|
<string name="address_book_delete_last_address">"%1$s\" tiene solo una dirección. Si la eliminas, también se eliminará el contacto. ¿Continuar?"</string>
|
||||||
<string name="address_book_deleting_error">No se pudo eliminar el contacto. Inténtelo de nuevo más tarde.</string>
|
<string name="address_book_deleting_error">No se pudo eliminar el contacto. Inténtelo de nuevo más tarde.</string>
|
||||||
<string name="address_book_description">Gestionar contactos y direcciones</string>
|
<string name="address_book_description">Gestionar contactos y direcciones</string>
|
||||||
<string name="address_book_discard">Descartar</string>
|
<string name="address_book_discard">Descartar</string>
|
||||||
|
|
@ -114,11 +121,22 @@
|
||||||
<string name="address_book_enter_address">Introduzca la dirección</string>
|
<string name="address_book_enter_address">Introduzca la dirección</string>
|
||||||
<string name="address_book_invalid_address_error">Dirección no válida</string>
|
<string name="address_book_invalid_address_error">Dirección no válida</string>
|
||||||
<string name="address_book_keep_editing">Seguir editando</string>
|
<string name="address_book_keep_editing">Seguir editando</string>
|
||||||
|
<string name="address_book_max_networks_alert_description">No puede crear más de 20 direcciones. Elimine una para añadir una nueva.</string>
|
||||||
|
<string name="address_book_max_networks_alert_title">No se puede agregar una nueva dirección</string>
|
||||||
|
<string name="address_book_name_empty_error">Se requiere el nombre del contacto.</string>
|
||||||
|
<string name="address_book_name_invalid_chars_error">El nombre del contacto contiene caracteres no válidos.</string>
|
||||||
|
<string name="address_book_name_max_chars_error">El nombre de contacto no debe superar los 50 caracteres</string>
|
||||||
|
<string name="address_book_name_taken_error">Ese nombre ya está en uso en esta billetera</string>
|
||||||
<string name="address_book_new_contact">Nuevo contacto</string>
|
<string name="address_book_new_contact">Nuevo contacto</string>
|
||||||
<string name="address_book_no_contacts">Aún no hay contactos</string>
|
<string name="address_book_no_contacts">Aún no hay contactos</string>
|
||||||
<string name="address_book_no_contacts_description">Los contactos añadidos aparecerán aquí</string>
|
<string name="address_book_no_contacts_description">Los contactos añadidos aparecerán aquí</string>
|
||||||
<string name="address_book_remove_address">Eliminar dirección</string>
|
<string name="address_book_remove_address">Eliminar dirección</string>
|
||||||
|
<string name="address_book_save_address">Guardar dirección</string>
|
||||||
|
<string name="address_book_save_contact">Guardar contacto</string>
|
||||||
|
<string name="address_book_save_to_wallet_title">Guardar en la billetera</string>
|
||||||
<string name="address_book_save_wallet_to_description">Este contacto se añadirá a la agenda de esta billetera.</string>
|
<string name="address_book_save_wallet_to_description">Este contacto se añadirá a la agenda de esta billetera.</string>
|
||||||
|
<string name="address_book_search_no_results">No se encontraron resultados.\nPruebe con otro nombre.</string>
|
||||||
|
<string name="address_book_select_all_networks">Seleccionar todo</string>
|
||||||
<string name="address_book_select_network">Seleccionar red</string>
|
<string name="address_book_select_network">Seleccionar red</string>
|
||||||
<string name="address_book_title">Libreta de direcciones</string>
|
<string name="address_book_title">Libreta de direcciones</string>
|
||||||
<string name="address_book_unsaved_changes">Cambios no guardados</string>
|
<string name="address_book_unsaved_changes">Cambios no guardados</string>
|
||||||
|
|
|
||||||
|
|
@ -1864,6 +1864,9 @@
|
||||||
<string name="tangempay_card_details_add_funds">Add funds</string>
|
<string name="tangempay_card_details_add_funds">Add funds</string>
|
||||||
<string name="tangempay_card_details_add_funds_subtitle">Top-up options</string>
|
<string name="tangempay_card_details_add_funds_subtitle">Top-up options</string>
|
||||||
<string name="tangempay_card_details_add_to_wallet_button_text">Add to Google Wallet</string>
|
<string name="tangempay_card_details_add_to_wallet_button_text">Add to Google Wallet</string>
|
||||||
|
<string name="tangempay_card_details_awaiting_deposit_cancel_button">Cancel %1$s, move to %2$s</string>
|
||||||
|
<string name="tangempay_card_details_awaiting_deposit_subtitle">To pay monthly fee for plan and start use card</string>
|
||||||
|
<string name="tangempay_card_details_awaiting_deposit_title">Top-up your account on %1$s</string>
|
||||||
<string name="tangempay_card_details_card_number">Card Number</string>
|
<string name="tangempay_card_details_card_number">Card Number</string>
|
||||||
<string name="tangempay_card_details_change_pin">PIN code</string>
|
<string name="tangempay_card_details_change_pin">PIN code</string>
|
||||||
<string name="tangempay_card_details_change_pin_success_description">The card is fully ready for payments.</string>
|
<string name="tangempay_card_details_change_pin_success_description">The card is fully ready for payments.</string>
|
||||||
|
|
@ -1898,6 +1901,8 @@
|
||||||
<string name="tangempay_card_details_rename_card_placeholder">Card name</string>
|
<string name="tangempay_card_details_rename_card_placeholder">Card name</string>
|
||||||
<string name="tangempay_card_details_reveal_text">Reveal</string>
|
<string name="tangempay_card_details_reveal_text">Reveal</string>
|
||||||
<string name="tangempay_card_details_show_details">Details</string>
|
<string name="tangempay_card_details_show_details">Details</string>
|
||||||
|
<string name="tangempay_card_details_system_downgrade_subtitle">If it will remain below zero your %1$s cards will be closed on %2$s</string>
|
||||||
|
<string name="tangempay_card_details_system_downgrade_title">Top up your account shortly</string>
|
||||||
<string name="tangempay_card_details_title">Details</string>
|
<string name="tangempay_card_details_title">Details</string>
|
||||||
<string name="tangempay_card_details_unable_to_rename_card_description">Please try again later</string>
|
<string name="tangempay_card_details_unable_to_rename_card_description">Please try again later</string>
|
||||||
<string name="tangempay_card_details_unfreeze_card">Unfreeze Card</string>
|
<string name="tangempay_card_details_unfreeze_card">Unfreeze Card</string>
|
||||||
|
|
@ -1933,9 +1938,14 @@
|
||||||
<string name="tangempay_come_back_if_forget_pin">Come back to the app if you forget it.</string>
|
<string name="tangempay_come_back_if_forget_pin">Come back to the app if you forget it.</string>
|
||||||
<string name="tangempay_common_card">Card</string>
|
<string name="tangempay_common_card">Card</string>
|
||||||
<string name="tangempay_common_error_loading">Error loading</string>
|
<string name="tangempay_common_error_loading">Error loading</string>
|
||||||
|
<string name="tangempay_current_plan_active_till_notification">Your %1$s plan is active till %2$s, then we will move you to %3$s. %4$s won\'t be charged.</string>
|
||||||
<string name="tangempay_current_plan_change">Change plan</string>
|
<string name="tangempay_current_plan_change">Change plan</string>
|
||||||
|
<string name="tangempay_current_plan_fee_charged_notification">%1$s monthly fee will be charged on %2$s</string>
|
||||||
<string name="tangempay_current_plan_section_card">Card related</string>
|
<string name="tangempay_current_plan_section_card">Card related</string>
|
||||||
<string name="tangempay_current_plan_section_plan">Plan related</string>
|
<string name="tangempay_current_plan_section_plan">Plan related</string>
|
||||||
|
<string name="tangempay_current_plan_stay_button">Stay on %1$s</string>
|
||||||
|
<string name="tangempay_current_plan_stay_sheet_body">Your transition on %1$s will be canceled</string>
|
||||||
|
<string name="tangempay_current_plan_stay_sheet_title">Do you want to stay on %1$s?</string>
|
||||||
<string name="tangempay_current_plan_title">Current plan</string>
|
<string name="tangempay_current_plan_title">Current plan</string>
|
||||||
<string name="tangempay_daily_limit_hint" formatted="false">Set a limit from %s to %s</string>
|
<string name="tangempay_daily_limit_hint" formatted="false">Set a limit from %s to %s</string>
|
||||||
<string name="tangempay_daily_limit_set_button">Set limits</string>
|
<string name="tangempay_daily_limit_set_button">Set limits</string>
|
||||||
|
|
@ -2047,7 +2057,16 @@
|
||||||
<string name="tangempay_select_plan_btn_select">Select</string>
|
<string name="tangempay_select_plan_btn_select">Select</string>
|
||||||
<string name="tangempay_select_plan_btn_upgrade">Upgrade plan</string>
|
<string name="tangempay_select_plan_btn_upgrade">Upgrade plan</string>
|
||||||
<string name="tangempay_select_plan_compare">Compare plans</string>
|
<string name="tangempay_select_plan_compare">Compare plans</string>
|
||||||
|
<string name="tangempay_select_plan_confirm_downgrade_title">Your %1$s plan and %2$s cards will be active till %3$s</string>
|
||||||
|
<string name="tangempay_select_plan_confirm_point_cancel_till">You can cancel this transition till %1$s</string>
|
||||||
|
<string name="tangempay_select_plan_confirm_point_cards_closed">Your %1$s cards will be closed</string>
|
||||||
|
<string name="tangempay_select_plan_confirm_point_monthly_fee">%1$s monthly fee will be taken from your account</string>
|
||||||
|
<string name="tangempay_select_plan_confirm_point_move_on_date">On %1$s we will move you to %2$s plan</string>
|
||||||
|
<string name="tangempay_select_plan_confirm_point_no_fee">No fee applied</string>
|
||||||
|
<string name="tangempay_select_plan_confirm_point_virtual_card">You will get your virtual %1$s in minutes</string>
|
||||||
|
<string name="tangempay_select_plan_confirm_switch_title">You are switching to %1$s</string>
|
||||||
<string name="tangempay_select_plan_confirm_title">Confirm selection</string>
|
<string name="tangempay_select_plan_confirm_title">Confirm selection</string>
|
||||||
|
<string name="tangempay_select_plan_confirm_upgrade_title">We will issue %1$s for you</string>
|
||||||
<string name="tangempay_select_plan_title">Select plan</string>
|
<string name="tangempay_select_plan_title">Select plan</string>
|
||||||
<string name="tangempay_service_unavailable_description">We’re fixing a technical issue. Please try again later.</string>
|
<string name="tangempay_service_unavailable_description">We’re fixing a technical issue. Please try again later.</string>
|
||||||
<string name="tangempay_service_unavailable_title">Service temporarily unavailable</string>
|
<string name="tangempay_service_unavailable_title">Service temporarily unavailable</string>
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,29 @@ package com.tangem.data.pay.converter
|
||||||
|
|
||||||
import com.tangem.datasource.api.pay.models.response.CustomerMeResponse
|
import com.tangem.datasource.api.pay.models.response.CustomerMeResponse
|
||||||
import com.tangem.domain.models.account.TangemPayTariffPlan
|
import com.tangem.domain.models.account.TangemPayTariffPlan
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
internal object TangemPayTariffPlanConverter {
|
internal object TangemPayTariffPlanConverter {
|
||||||
|
|
||||||
fun convert(value: CustomerMeResponse.TariffPlan?): TangemPayTariffPlan? {
|
fun convert(value: CustomerMeResponse.TariffPlan?): TangemPayTariffPlan? {
|
||||||
val id = value?.id ?: return null
|
val id = value?.id ?: return null
|
||||||
val name = value.name ?: return null
|
val name = value.name ?: return null
|
||||||
|
val programName = value.programName ?: return null
|
||||||
|
|
||||||
|
// We cannot base our logic on knowledge what exact tier type is it.
|
||||||
|
// Use it only as identifier to get data from other responses
|
||||||
|
val tierId = value.type ?: return null
|
||||||
|
|
||||||
|
// Basic tier is a default tier. We can base some features on it.
|
||||||
|
// Other tiers are adjusted from admin panel. It is not guaranteed to have it in future
|
||||||
|
val isBasicTier = tierId.uppercase(Locale.US) == "BASIC"
|
||||||
|
|
||||||
return TangemPayTariffPlan(
|
return TangemPayTariffPlan(
|
||||||
id = id,
|
id = id,
|
||||||
type = TangemPayTariffPlan.Type.fromString(value.type),
|
tierId = tierId,
|
||||||
|
isBasicTier = isBasicTier,
|
||||||
name = name,
|
name = name,
|
||||||
|
programName = programName,
|
||||||
descriptionItems = value.descriptionItems.orEmpty().mapNotNull(::convertDescriptionItem),
|
descriptionItems = value.descriptionItems.orEmpty().mapNotNull(::convertDescriptionItem),
|
||||||
images = value.images.orEmpty().mapNotNull(::convertImage),
|
images = value.images.orEmpty().mapNotNull(::convertImage),
|
||||||
fees = value.fees.orEmpty().mapNotNull(::convertFee),
|
fees = value.fees.orEmpty().mapNotNull(::convertFee),
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,30 @@ internal class TangemPayTariffPlanConverterTest {
|
||||||
assertThat(TangemPayTariffPlanConverter.convert(value)).isNull()
|
assertThat(TangemPayTariffPlanConverter.convert(value)).isNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN missing type WHEN convert THEN returns null`() {
|
||||||
|
val value = tariffPlan(type = null)
|
||||||
|
|
||||||
|
assertThat(TangemPayTariffPlanConverter.convert(value)).isNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN missing programName WHEN convert THEN returns null`() {
|
||||||
|
val value = tariffPlan(programName = null)
|
||||||
|
|
||||||
|
assertThat(TangemPayTariffPlanConverter.convert(value)).isNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN basic tier in mixed case WHEN convert THEN isBasicTier is true`() {
|
||||||
|
val value = tariffPlan(type = "Basic")
|
||||||
|
|
||||||
|
val result = TangemPayTariffPlanConverter.convert(value)
|
||||||
|
|
||||||
|
assertThat(result?.tierId).isEqualTo("Basic")
|
||||||
|
assertThat(result?.isBasicTier).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `GIVEN full valid plan WHEN convert THEN maps all fields`() {
|
fun `GIVEN full valid plan WHEN convert THEN maps all fields`() {
|
||||||
// GIVEN
|
// GIVEN
|
||||||
|
|
@ -58,8 +82,10 @@ internal class TangemPayTariffPlanConverterTest {
|
||||||
// THEN
|
// THEN
|
||||||
val expected = TangemPayTariffPlan(
|
val expected = TangemPayTariffPlan(
|
||||||
id = PLAN_ID,
|
id = PLAN_ID,
|
||||||
type = TangemPayTariffPlan.Type.PLUS,
|
tierId = "PLUS",
|
||||||
|
isBasicTier = false,
|
||||||
name = PLAN_NAME,
|
name = PLAN_NAME,
|
||||||
|
programName = PROGRAM_NAME,
|
||||||
descriptionItems = listOf(
|
descriptionItems = listOf(
|
||||||
TangemPayTariffPlan.DescriptionItem(
|
TangemPayTariffPlan.DescriptionItem(
|
||||||
section = TangemPayTariffPlan.Section.PLAN_RELATED,
|
section = TangemPayTariffPlan.Section.PLAN_RELATED,
|
||||||
|
|
@ -110,8 +136,10 @@ internal class TangemPayTariffPlanConverterTest {
|
||||||
// THEN
|
// THEN
|
||||||
val expected = TangemPayTariffPlan(
|
val expected = TangemPayTariffPlan(
|
||||||
id = PLAN_ID,
|
id = PLAN_ID,
|
||||||
type = TangemPayTariffPlan.Type.UNKNOWN,
|
tierId = "SOMETHING_NEW",
|
||||||
|
isBasicTier = false,
|
||||||
name = PLAN_NAME,
|
name = PLAN_NAME,
|
||||||
|
programName = PROGRAM_NAME,
|
||||||
descriptionItems = listOf(
|
descriptionItems = listOf(
|
||||||
TangemPayTariffPlan.DescriptionItem(
|
TangemPayTariffPlan.DescriptionItem(
|
||||||
section = TangemPayTariffPlan.Section.UNKNOWN,
|
section = TangemPayTariffPlan.Section.UNKNOWN,
|
||||||
|
|
@ -168,6 +196,7 @@ internal class TangemPayTariffPlanConverterTest {
|
||||||
id: String? = PLAN_ID,
|
id: String? = PLAN_ID,
|
||||||
type: String? = "BASIC",
|
type: String? = "BASIC",
|
||||||
name: String? = PLAN_NAME,
|
name: String? = PLAN_NAME,
|
||||||
|
programName: String? = PROGRAM_NAME,
|
||||||
descriptionItems: List<CustomerMeResponse.DescriptionItem>? = null,
|
descriptionItems: List<CustomerMeResponse.DescriptionItem>? = null,
|
||||||
images: List<CustomerMeResponse.Image>? = null,
|
images: List<CustomerMeResponse.Image>? = null,
|
||||||
fees: List<CustomerMeResponse.Fee>? = null,
|
fees: List<CustomerMeResponse.Fee>? = null,
|
||||||
|
|
@ -175,6 +204,7 @@ internal class TangemPayTariffPlanConverterTest {
|
||||||
id = id,
|
id = id,
|
||||||
type = type,
|
type = type,
|
||||||
name = name,
|
name = name,
|
||||||
|
programName = programName,
|
||||||
descriptionItems = descriptionItems,
|
descriptionItems = descriptionItems,
|
||||||
images = images,
|
images = images,
|
||||||
fees = fees,
|
fees = fees,
|
||||||
|
|
@ -183,5 +213,6 @@ internal class TangemPayTariffPlanConverterTest {
|
||||||
private companion object {
|
private companion object {
|
||||||
const val PLAN_ID = "plan-1"
|
const val PLAN_ID = "plan-1"
|
||||||
const val PLAN_NAME = "Plus"
|
const val PLAN_NAME = "Plus"
|
||||||
|
const val PROGRAM_NAME = "program-1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -120,8 +120,10 @@ internal class DefaultPaymentAccountStatusFetcherTest {
|
||||||
|
|
||||||
private val basicPlan = TangemPayTariffPlan(
|
private val basicPlan = TangemPayTariffPlan(
|
||||||
id = "plan_basic",
|
id = "plan_basic",
|
||||||
type = TangemPayTariffPlan.Type.BASIC,
|
tierId = "BASIC",
|
||||||
|
isBasicTier = true,
|
||||||
name = "Basic",
|
name = "Basic",
|
||||||
|
programName = "program_basic",
|
||||||
descriptionItems = emptyList(),
|
descriptionItems = emptyList(),
|
||||||
images = emptyList(),
|
images = emptyList(),
|
||||||
fees = emptyList(),
|
fees = emptyList(),
|
||||||
|
|
|
||||||
|
|
@ -91,8 +91,10 @@ internal class DefaultTariffPlanTransitionsRepositoryTest {
|
||||||
type = TangemPayTariffPlanTransition.Type.UPGRADE,
|
type = TangemPayTariffPlanTransition.Type.UPGRADE,
|
||||||
plan = TangemPayTariffPlan(
|
plan = TangemPayTariffPlan(
|
||||||
id = PLAN_ID,
|
id = PLAN_ID,
|
||||||
type = TangemPayTariffPlan.Type.PLUS,
|
tierId = "PLUS",
|
||||||
|
isBasicTier = false,
|
||||||
name = PLAN_NAME,
|
name = PLAN_NAME,
|
||||||
|
programName = PROGRAM_NAME,
|
||||||
descriptionItems = emptyList(),
|
descriptionItems = emptyList(),
|
||||||
images = emptyList(),
|
images = emptyList(),
|
||||||
fees = emptyList(),
|
fees = emptyList(),
|
||||||
|
|
@ -187,6 +189,7 @@ internal class DefaultTariffPlanTransitionsRepositoryTest {
|
||||||
id = id,
|
id = id,
|
||||||
type = "PLUS",
|
type = "PLUS",
|
||||||
name = PLAN_NAME,
|
name = PLAN_NAME,
|
||||||
|
programName = PROGRAM_NAME,
|
||||||
descriptionItems = null,
|
descriptionItems = null,
|
||||||
images = null,
|
images = null,
|
||||||
fees = null,
|
fees = null,
|
||||||
|
|
@ -197,6 +200,7 @@ internal class DefaultTariffPlanTransitionsRepositoryTest {
|
||||||
const val AUTH_HEADER = "auth-header"
|
const val AUTH_HEADER = "auth-header"
|
||||||
const val PLAN_ID = "plan-plus"
|
const val PLAN_ID = "plan-plus"
|
||||||
const val PLAN_NAME = "Plus"
|
const val PLAN_NAME = "Plus"
|
||||||
|
const val PROGRAM_NAME = "program-plus"
|
||||||
const val PENDING_PLAN_ID = "plan-basic"
|
const val PENDING_PLAN_ID = "plan-basic"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,8 +8,10 @@ import java.util.Locale
|
||||||
@Serializable
|
@Serializable
|
||||||
data class TangemPayTariffPlan(
|
data class TangemPayTariffPlan(
|
||||||
@SerialName("id") val id: String,
|
@SerialName("id") val id: String,
|
||||||
@SerialName("type") val type: Type,
|
@SerialName("tier_id") val tierId: String,
|
||||||
|
@SerialName("is_basic_tier") val isBasicTier: Boolean,
|
||||||
@SerialName("name") val name: String,
|
@SerialName("name") val name: String,
|
||||||
|
@SerialName("program_name") val programName: String,
|
||||||
@SerialName("description_items") val descriptionItems: List<DescriptionItem>,
|
@SerialName("description_items") val descriptionItems: List<DescriptionItem>,
|
||||||
@SerialName("images") val images: List<Image> = emptyList(),
|
@SerialName("images") val images: List<Image> = emptyList(),
|
||||||
@SerialName("fees") val fees: List<Fee> = emptyList(),
|
@SerialName("fees") val fees: List<Fee> = emptyList(),
|
||||||
|
|
@ -100,31 +102,6 @@ data class TangemPayTariffPlan(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
|
||||||
enum class Type {
|
|
||||||
@SerialName("BASIC")
|
|
||||||
BASIC,
|
|
||||||
|
|
||||||
@SerialName("PLUS")
|
|
||||||
PLUS,
|
|
||||||
|
|
||||||
@SerialName("PLUS_FF")
|
|
||||||
PLUS_FF,
|
|
||||||
|
|
||||||
@SerialName("UNKNOWN")
|
|
||||||
UNKNOWN,
|
|
||||||
;
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun fromString(value: String?) = when (value?.uppercase(Locale.US)) {
|
|
||||||
"BASIC" -> BASIC
|
|
||||||
"PLUS" -> PLUS
|
|
||||||
"PLUS_FF" -> PLUS_FF
|
|
||||||
else -> UNKNOWN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class Section {
|
enum class Section {
|
||||||
@SerialName("CARD_RELATED")
|
@SerialName("CARD_RELATED")
|
||||||
|
|
|
||||||
|
|
@ -153,14 +153,18 @@ internal class GetTangemPayTariffPlanStateUseCaseTest {
|
||||||
|
|
||||||
val CURRENT_PLAN = TangemPayTariffPlan(
|
val CURRENT_PLAN = TangemPayTariffPlan(
|
||||||
id = "plan-basic",
|
id = "plan-basic",
|
||||||
type = TangemPayTariffPlan.Type.BASIC,
|
tierId = "BASIC",
|
||||||
|
isBasicTier = true,
|
||||||
name = "Basic",
|
name = "Basic",
|
||||||
|
programName = "program-basic",
|
||||||
descriptionItems = emptyList(),
|
descriptionItems = emptyList(),
|
||||||
)
|
)
|
||||||
val TARGET_PLAN = TangemPayTariffPlan(
|
val TARGET_PLAN = TangemPayTariffPlan(
|
||||||
id = TARGET_PLAN_ID,
|
id = TARGET_PLAN_ID,
|
||||||
type = TangemPayTariffPlan.Type.PLUS,
|
tierId = "PLUS",
|
||||||
|
isBasicTier = false,
|
||||||
name = "Plus",
|
name = "Plus",
|
||||||
|
programName = "program-plus",
|
||||||
descriptionItems = emptyList(),
|
descriptionItems = emptyList(),
|
||||||
)
|
)
|
||||||
val CUSTOMER_TARIFF = TangemPayCustomerTariffPlan(
|
val CUSTOMER_TARIFF = TangemPayCustomerTariffPlan(
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
package com.tangem.features.tangempay.cashback.impl.model
|
package com.tangem.features.tangempay.cashback.impl.model
|
||||||
|
|
||||||
import com.tangem.domain.models.account.TangemPayTariffPlan
|
|
||||||
|
|
||||||
/** Cashback program tier, mapped once from the domain and shared by the rate tile and the details sheet. */
|
/** Cashback program tier, mapped once from the domain and shared by the rate tile and the details sheet. */
|
||||||
internal data class CashbackTier(
|
internal data class CashbackTier(
|
||||||
val planType: TangemPayTariffPlan.Type,
|
val tierId: String,
|
||||||
val rate: Int?,
|
val rate: Int?,
|
||||||
val label: String,
|
val label: String,
|
||||||
val scope: String,
|
val scope: String,
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,13 @@ internal class TangemPayCashbackInfoTilesConverter(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// TODO([REDACTED_TASK_KEY]): move hardcoded strings to string resources
|
// TODO([REDACTED_TASK_KEY]): move hardcoded strings to string resources
|
||||||
fun convert(
|
fun convert(tiers: List<CashbackTier>, currentPlan: TangemPayTariffPlan?): TangemPayCashbackInfoTilesUM {
|
||||||
tiers: List<CashbackTier>,
|
val rate = tiers.selectTier(currentPlan?.tierId)?.rate
|
||||||
currentPlanType: TangemPayTariffPlan.Type,
|
|
||||||
currentPlanName: String?,
|
|
||||||
): TangemPayCashbackInfoTilesUM {
|
|
||||||
val rate = tiers.selectTier(currentPlanType)?.rate
|
|
||||||
return TangemPayCashbackInfoTilesUM(
|
return TangemPayCashbackInfoTilesUM(
|
||||||
rate = TangemPayCashbackInfoTilesUM.Tile(
|
rate = TangemPayCashbackInfoTilesUM.Tile(
|
||||||
iconRes = R.drawable.ic_percent_24,
|
iconRes = R.drawable.ic_percent_24,
|
||||||
title = stringReference(if (rate != null) "Cashback $rate%" else "Cashback"),
|
title = stringReference(if (rate != null) "Cashback $rate%" else "Cashback"),
|
||||||
subtitle = currentPlanName?.let { stringReference("With your $it plan") } ?: TextReference.EMPTY,
|
subtitle = currentPlan?.name?.let { stringReference("With your $it plan") } ?: TextReference.EMPTY,
|
||||||
onClick = onRateClick,
|
onClick = onRateClick,
|
||||||
),
|
),
|
||||||
accruals = TangemPayCashbackInfoTilesUM.Tile(
|
accruals = TangemPayCashbackInfoTilesUM.Tile(
|
||||||
|
|
@ -34,9 +30,7 @@ internal class TangemPayCashbackInfoTilesConverter(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<CashbackTier>.selectTier(planType: TangemPayTariffPlan.Type): CashbackTier? {
|
private fun List<CashbackTier>.selectTier(tierId: String?): CashbackTier? {
|
||||||
return firstOrNull {
|
return firstOrNull { it.tierId == tierId } ?: firstOrNull()
|
||||||
planType != TangemPayTariffPlan.Type.UNKNOWN && it.planType == planType
|
|
||||||
} ?: firstOrNull()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -86,8 +86,7 @@ internal class TangemPayCashbackModel @Inject constructor(
|
||||||
infoTiles = promotions?.let {
|
infoTiles = promotions?.let {
|
||||||
infoTilesConverter.convert(
|
infoTilesConverter.convert(
|
||||||
tiers = tiers,
|
tiers = tiers,
|
||||||
currentPlanType = plan?.type ?: TangemPayTariffPlan.Type.UNKNOWN,
|
currentPlan = plan,
|
||||||
currentPlanName = plan?.name,
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import com.tangem.core.ui.format.bigdecimal.fiat
|
||||||
import com.tangem.core.ui.format.bigdecimal.format
|
import com.tangem.core.ui.format.bigdecimal.format
|
||||||
import com.tangem.core.ui.format.bigdecimal.getJavaCurrencyByCode
|
import com.tangem.core.ui.format.bigdecimal.getJavaCurrencyByCode
|
||||||
import com.tangem.core.ui.format.bigdecimal.optionalDecimals
|
import com.tangem.core.ui.format.bigdecimal.optionalDecimals
|
||||||
import com.tangem.domain.models.account.TangemPayTariffPlan
|
|
||||||
import com.tangem.domain.pay.model.CashbackPromotions
|
import com.tangem.domain.pay.model.CashbackPromotions
|
||||||
import com.tangem.utils.converter.Converter
|
import com.tangem.utils.converter.Converter
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
@ -14,7 +13,7 @@ internal class TangemPayCashbackTiersConverter : Converter<CashbackPromotions, L
|
||||||
override fun convert(value: CashbackPromotions): List<CashbackTier> {
|
override fun convert(value: CashbackPromotions): List<CashbackTier> {
|
||||||
return value.cardTiers.map { tier ->
|
return value.cardTiers.map { tier ->
|
||||||
CashbackTier(
|
CashbackTier(
|
||||||
planType = TangemPayTariffPlan.Type.fromString(tier.tier),
|
tierId = tier.tier,
|
||||||
rate = CashbackRates.forTier(tier.tier),
|
rate = CashbackRates.forTier(tier.tier),
|
||||||
label = tier.label,
|
label = tier.label,
|
||||||
scope = tier.scope,
|
scope = tier.scope,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package com.tangem.features.tangempay.entity
|
||||||
|
|
||||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.wrappedList
|
||||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||||
import com.tangem.domain.models.account.TangemPayCustomerTariffPlan
|
import com.tangem.domain.models.account.TangemPayCustomerTariffPlan
|
||||||
import com.tangem.domain.models.account.TangemPayTariffPlanState
|
import com.tangem.domain.models.account.TangemPayTariffPlanState
|
||||||
|
|
@ -37,7 +37,6 @@ internal class TangemPayDetailsNotificationFactory(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO v_rodionov: #[REDACTED_TASK_KEY] fix hardcoded strings
|
|
||||||
fun createAwaitingDepositConfig(tariffPlan: TangemPayTariffPlanState?): NotificationConfig? {
|
fun createAwaitingDepositConfig(tariffPlan: TangemPayTariffPlanState?): NotificationConfig? {
|
||||||
if (!isTiersPlusPlanEnabled) return null
|
if (!isTiersPlusPlanEnabled) return null
|
||||||
if (tariffPlan == null) return null
|
if (tariffPlan == null) return null
|
||||||
|
|
@ -52,13 +51,15 @@ internal class TangemPayDetailsNotificationFactory(
|
||||||
|
|
||||||
val feeText = orderStep.toPlan.formatRecurringFeeOrNull() ?: return null
|
val feeText = orderStep.toPlan.formatRecurringFeeOrNull() ?: return null
|
||||||
|
|
||||||
val title = "Top-up your account on $feeText"
|
|
||||||
return NotificationConfig(
|
return NotificationConfig(
|
||||||
title = stringReference(title),
|
title = resourceReference(R.string.tangempay_card_details_awaiting_deposit_title, wrappedList(feeText)),
|
||||||
subtitle = stringReference("To pay monthly fee for plan and start use card"),
|
subtitle = resourceReference(R.string.tangempay_card_details_awaiting_deposit_subtitle),
|
||||||
iconResId = R.drawable.ic_alert_circle_24,
|
iconResId = R.drawable.ic_alert_circle_24,
|
||||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||||
text = stringReference("Cancel ${orderStep.toPlan.name}, move to ${orderStep.fromPlan.name}"),
|
text = resourceReference(
|
||||||
|
R.string.tangempay_card_details_awaiting_deposit_cancel_button,
|
||||||
|
wrappedList(orderStep.toPlan.name, orderStep.fromPlan.name),
|
||||||
|
),
|
||||||
onClick = { intents.onCancelPlusTransition(order.orderId) },
|
onClick = { intents.onCancelPlusTransition(order.orderId) },
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -81,16 +82,18 @@ internal class TangemPayDetailsNotificationFactory(
|
||||||
iconResId = if (isRedesignEnabled) R.drawable.ic_alert_circle_24 else R.drawable.img_attention_20,
|
iconResId = if (isRedesignEnabled) R.drawable.ic_alert_circle_24 else R.drawable.img_attention_20,
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO v_rodionov: #[REDACTED_TASK_KEY] fix hardcoded strings
|
|
||||||
private fun createTariffSystemDownGradePendingConfig(tariffPlan: TangemPayTariffPlanState): NotificationConfig? {
|
private fun createTariffSystemDownGradePendingConfig(tariffPlan: TangemPayTariffPlanState): NotificationConfig? {
|
||||||
val date = tariffPlan.tariff.formatNextBillingDateOrNull() ?: return null
|
val date = tariffPlan.tariff.formatNextBillingDateOrNull() ?: return null
|
||||||
val planName = tariffPlan.tariff.plan.name
|
val planName = tariffPlan.tariff.plan.name
|
||||||
return NotificationConfig(
|
return NotificationConfig(
|
||||||
title = stringReference("Top up your account shortly"),
|
title = resourceReference(R.string.tangempay_card_details_system_downgrade_title),
|
||||||
subtitle = stringReference("If it will remain below zero your $planName cards will be closed on $date"),
|
subtitle = resourceReference(
|
||||||
|
R.string.tangempay_card_details_system_downgrade_subtitle,
|
||||||
|
wrappedList(planName, date),
|
||||||
|
),
|
||||||
iconResId = R.drawable.ic_alert_circle_24,
|
iconResId = R.drawable.ic_alert_circle_24,
|
||||||
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(
|
||||||
text = stringReference("Add funds"),
|
text = resourceReference(R.string.tangempay_card_details_add_funds),
|
||||||
onClick = intents::onClickAddFunds,
|
onClick = intents::onClickAddFunds,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import com.tangem.core.ui.res.generated.icons.Icons
|
||||||
import com.tangem.core.ui.res.generated.icons.ic_document_20
|
import com.tangem.core.ui.res.generated.icons.ic_document_20
|
||||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||||
import com.tangem.domain.models.account.TangemPayCustomerTariffPlan
|
import com.tangem.domain.models.account.TangemPayCustomerTariffPlan
|
||||||
import com.tangem.domain.models.account.TangemPayTariffPlan
|
|
||||||
import com.tangem.domain.models.account.TangemPayTariffPlanState
|
import com.tangem.domain.models.account.TangemPayTariffPlanState
|
||||||
import com.tangem.domain.models.pay.TangemPayCard
|
import com.tangem.domain.models.pay.TangemPayCard
|
||||||
import com.tangem.domain.models.pay.TangemPayCardFrozenState
|
import com.tangem.domain.models.pay.TangemPayCardFrozenState
|
||||||
|
|
@ -286,10 +285,7 @@ internal class TangemPayDetailsStateFactory(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (isTiersPlusPlanEnabled &&
|
if (isTiersPlusPlanEnabled && tariffPlan != null && !tariffPlan.tariff.plan.isBasicTier) {
|
||||||
tariffPlan != null &&
|
|
||||||
tariffPlan.tariff.plan.type != TangemPayTariffPlan.Type.BASIC
|
|
||||||
) {
|
|
||||||
add(
|
add(
|
||||||
TangemPayDropDownItemUM(
|
TangemPayDropDownItemUM(
|
||||||
title = resourceReference(R.string.tangempay_visa_benefits),
|
title = resourceReference(R.string.tangempay_visa_benefits),
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import com.tangem.core.decompose.model.ParamsContainer
|
||||||
import com.tangem.core.decompose.navigation.Router
|
import com.tangem.core.decompose.navigation.Router
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
|
import com.tangem.core.ui.extensions.wrappedList
|
||||||
import com.tangem.core.decompose.ui.UiMessageSender
|
import com.tangem.core.decompose.ui.UiMessageSender
|
||||||
import com.tangem.core.ui.utils.DateTimeFormatters
|
import com.tangem.core.ui.utils.DateTimeFormatters
|
||||||
import com.tangem.domain.models.account.TangemPayCustomerTariffPlan
|
import com.tangem.domain.models.account.TangemPayCustomerTariffPlan
|
||||||
|
|
@ -50,7 +51,6 @@ internal class TangemPayCurrentPlanModel @Inject constructor(
|
||||||
onChangePlanClick = { router.push(TangemPayAccountDetailsInnerRoute.SelectPlan(params.tariffPlan)) },
|
onChangePlanClick = { router.push(TangemPayAccountDetailsInnerRoute.SelectPlan(params.tariffPlan)) },
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO v_rodionov: #[REDACTED_TASK_KEY] fix hardcoded strings
|
|
||||||
private fun createNotification(customerPlan: TangemPayCustomerTariffPlan): TangemPayCurrentPlanUM.Notification? {
|
private fun createNotification(customerPlan: TangemPayCustomerTariffPlan): TangemPayCurrentPlanUM.Notification? {
|
||||||
val date = customerPlan.formatNextBillingDateOrNull(formatter = DateTimeFormatters.dateMMMd) ?: return null
|
val date = customerPlan.formatNextBillingDateOrNull(formatter = DateTimeFormatters.dateMMMd) ?: return null
|
||||||
val feeText = customerPlan.plan.formatRecurringFeeOrNull() ?: return null
|
val feeText = customerPlan.plan.formatRecurringFeeOrNull() ?: return null
|
||||||
|
|
@ -58,19 +58,25 @@ internal class TangemPayCurrentPlanModel @Inject constructor(
|
||||||
TangemPayCustomerTariffPlan.Status.DOWNGRADE_PENDING -> {
|
TangemPayCustomerTariffPlan.Status.DOWNGRADE_PENDING -> {
|
||||||
val targetPlan = customerPlan.pendingPlan ?: return null
|
val targetPlan = customerPlan.pendingPlan ?: return null
|
||||||
TangemPayCurrentPlanUM.Notification(
|
TangemPayCurrentPlanUM.Notification(
|
||||||
text = stringReference(
|
text = resourceReference(
|
||||||
"Your ${customerPlan.plan.name} plan is active till $date, then we will move you to " +
|
R.string.tangempay_current_plan_active_till_notification,
|
||||||
"${targetPlan.name}. $feeText won't be charged.",
|
wrappedList(customerPlan.plan.name, date, targetPlan.name, feeText),
|
||||||
),
|
),
|
||||||
button = TangemPayCurrentPlanUM.Notification.Button(
|
button = TangemPayCurrentPlanUM.Notification.Button(
|
||||||
text = stringReference("Stay on ${customerPlan.plan.name}"),
|
text = resourceReference(
|
||||||
|
R.string.tangempay_current_plan_stay_button,
|
||||||
|
wrappedList(customerPlan.plan.name),
|
||||||
|
),
|
||||||
isProcessing = isProcessing,
|
isProcessing = isProcessing,
|
||||||
onClick = ::onStayOnPlanClick,
|
onClick = ::onStayOnPlanClick,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
TangemPayCustomerTariffPlan.Status.ACTIVE -> TangemPayCurrentPlanUM.Notification(
|
TangemPayCustomerTariffPlan.Status.ACTIVE -> TangemPayCurrentPlanUM.Notification(
|
||||||
text = stringReference("$feeText monthly fee will be charged on $date"),
|
text = resourceReference(
|
||||||
|
R.string.tangempay_current_plan_fee_charged_notification,
|
||||||
|
wrappedList(feeText, date),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import com.tangem.core.decompose.navigation.Router
|
||||||
import com.tangem.core.decompose.ui.UiMessageSender
|
import com.tangem.core.decompose.ui.UiMessageSender
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
|
import com.tangem.core.ui.extensions.wrappedList
|
||||||
import com.tangem.core.ui.utils.DateTimeFormatters
|
import com.tangem.core.ui.utils.DateTimeFormatters
|
||||||
import com.tangem.domain.models.account.TangemPayTariffPlan
|
import com.tangem.domain.models.account.TangemPayTariffPlan
|
||||||
import com.tangem.domain.models.account.TangemPayTariffPlanTransition
|
import com.tangem.domain.models.account.TangemPayTariffPlanTransition
|
||||||
|
|
@ -189,28 +190,34 @@ internal class TangemPaySelectPlanModel @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO v_rodionov: #[REDACTED_TASK_KEY] fix hardcoded strings
|
|
||||||
private fun buildConfirmContent(): TangemPaySelectPlanUM.Content {
|
private fun buildConfirmContent(): TangemPaySelectPlanUM.Content {
|
||||||
val transition = allowedTransitions.getOrNull(selectedIndex) ?: return buildSelectContent()
|
val transition = allowedTransitions.getOrNull(selectedIndex) ?: return buildSelectContent()
|
||||||
val targetProgramme = transition.plan.name
|
val targetPlanName = transition.plan.name
|
||||||
|
val programName = transition.plan.programName
|
||||||
return TangemPaySelectPlanUM.Content.Confirm(
|
return TangemPaySelectPlanUM.Content.Confirm(
|
||||||
title = when (transition.type) {
|
title = when (transition.type) {
|
||||||
TangemPayTariffPlanTransition.Type.UPGRADE -> stringReference(
|
TangemPayTariffPlanTransition.Type.UPGRADE -> resourceReference(
|
||||||
"We will issue Visa $targetProgramme for you",
|
R.string.tangempay_select_plan_confirm_upgrade_title,
|
||||||
|
wrappedList(programName),
|
||||||
)
|
)
|
||||||
TangemPayTariffPlanTransition.Type.DOWNGRADE -> {
|
TangemPayTariffPlanTransition.Type.DOWNGRADE -> {
|
||||||
val nextBillingDate = nextBillingDate()
|
val nextBillingDate = nextBillingDate()
|
||||||
if (nextBillingDate != null) {
|
if (nextBillingDate != null) {
|
||||||
val programName = "UNKNOWN" // TODO v_rodionov: #[REDACTED_TASK_KEY] fix hardcoded strings
|
resourceReference(
|
||||||
val planName = params.tariffPlan.plan.name
|
R.string.tangempay_select_plan_confirm_downgrade_title,
|
||||||
stringReference(
|
wrappedList(params.tariffPlan.plan.name, programName, nextBillingDate),
|
||||||
"Your $planName plan and $programName cards will be active till $nextBillingDate",
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
stringReference("You are switching to $targetProgramme")
|
resourceReference(
|
||||||
|
R.string.tangempay_select_plan_confirm_switch_title,
|
||||||
|
wrappedList(targetPlanName),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> stringReference("You are switching to $targetProgramme")
|
else -> resourceReference(
|
||||||
|
R.string.tangempay_select_plan_confirm_switch_title,
|
||||||
|
wrappedList(targetPlanName),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
points = buildConfirmPoints(transition),
|
points = buildConfirmPoints(transition),
|
||||||
confirmButtonText = resourceReference(
|
confirmButtonText = resourceReference(
|
||||||
|
|
@ -226,18 +233,27 @@ internal class TangemPaySelectPlanModel @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO v_rodionov: #[REDACTED_TASK_KEY] fix hardcoded strings
|
|
||||||
private fun buildConfirmPoints(
|
private fun buildConfirmPoints(
|
||||||
transition: TangemPayTariffPlanTransition,
|
transition: TangemPayTariffPlanTransition,
|
||||||
): ImmutableList<TangemPaySelectPlanUM.PointUM> {
|
): ImmutableList<TangemPaySelectPlanUM.PointUM> {
|
||||||
val programName = "UNKNOWN" // TODO v_rodionov: #[REDACTED_TASK_KEY] fix hardcoded strings
|
val programName = transition.plan.programName
|
||||||
return when (transition.type) {
|
return when (transition.type) {
|
||||||
TangemPayTariffPlanTransition.Type.UPGRADE -> {
|
TangemPayTariffPlanTransition.Type.UPGRADE -> {
|
||||||
val feeText = transition.plan.formatRecurringFeeOrNull()
|
val feeText = transition.plan.formatRecurringFeeOrNull()
|
||||||
buildList {
|
buildList {
|
||||||
add("You will get your virtual Visa $programName in minutes")
|
add(
|
||||||
|
resourceReference(
|
||||||
|
R.string.tangempay_select_plan_confirm_point_virtual_card,
|
||||||
|
wrappedList(programName),
|
||||||
|
),
|
||||||
|
)
|
||||||
if (feeText != null) {
|
if (feeText != null) {
|
||||||
add("$feeText monthly fee will be taken from your account")
|
add(
|
||||||
|
resourceReference(
|
||||||
|
R.string.tangempay_select_plan_confirm_point_monthly_fee,
|
||||||
|
wrappedList(feeText),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -245,18 +261,33 @@ internal class TangemPaySelectPlanModel @Inject constructor(
|
||||||
val date = nextBillingDate()
|
val date = nextBillingDate()
|
||||||
buildList {
|
buildList {
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
add("On $date we will move you to ${transition.plan.name} plan")
|
add(
|
||||||
|
resourceReference(
|
||||||
|
R.string.tangempay_select_plan_confirm_point_move_on_date,
|
||||||
|
wrappedList(date, transition.plan.name),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
add("Your Visa $programName cards will be closed")
|
add(
|
||||||
|
resourceReference(
|
||||||
|
R.string.tangempay_select_plan_confirm_point_cards_closed,
|
||||||
|
wrappedList(programName),
|
||||||
|
),
|
||||||
|
)
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
add("You can cancel this transition till $date")
|
add(
|
||||||
|
resourceReference(
|
||||||
|
R.string.tangempay_select_plan_confirm_point_cancel_till,
|
||||||
|
wrappedList(date),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
add("No fee applied")
|
add(resourceReference(R.string.tangempay_select_plan_confirm_point_no_fee))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> listOf("No fee applied")
|
else -> listOf(resourceReference(R.string.tangempay_select_plan_confirm_point_no_fee))
|
||||||
}
|
}
|
||||||
.map { TangemPaySelectPlanUM.PointUM(title = stringReference(it), body = null) }
|
.map { TangemPaySelectPlanUM.PointUM(title = it, body = null) }
|
||||||
.toImmutableList()
|
.toImmutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import com.tangem.core.ui.R
|
||||||
import com.tangem.core.ui.components.bottomsheets.message.*
|
import com.tangem.core.ui.components.bottomsheets.message.*
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.wrappedList
|
||||||
import com.tangem.core.ui.message.BottomSheetMessage
|
import com.tangem.core.ui.message.BottomSheetMessage
|
||||||
import com.tangem.core.ui.message.DialogMessage
|
import com.tangem.core.ui.message.DialogMessage
|
||||||
import com.tangem.core.ui.message.bottomSheetMessage
|
import com.tangem.core.ui.message.bottomSheetMessage
|
||||||
|
|
@ -149,7 +149,6 @@ internal object TangemPayMessagesFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO v_rodionov: #[REDACTED_TASK_KEY] fix hardcoded strings
|
|
||||||
fun createStayOnPlanMessage(
|
fun createStayOnPlanMessage(
|
||||||
planName: String,
|
planName: String,
|
||||||
targetPlanName: String,
|
targetPlanName: String,
|
||||||
|
|
@ -161,15 +160,18 @@ internal object TangemPayMessagesFactory {
|
||||||
type = MessageBottomSheetUM.Icon.Type.Informative
|
type = MessageBottomSheetUM.Icon.Type.Informative
|
||||||
backgroundType = MessageBottomSheetUM.Icon.BackgroundType.Informative
|
backgroundType = MessageBottomSheetUM.Icon.BackgroundType.Informative
|
||||||
}
|
}
|
||||||
title = stringReference("Do you want to stay on $planName?")
|
title = resourceReference(R.string.tangempay_current_plan_stay_sheet_title, wrappedList(planName))
|
||||||
body = stringReference("Your transition on $targetPlanName will be canceled")
|
body = resourceReference(
|
||||||
|
R.string.tangempay_current_plan_stay_sheet_body,
|
||||||
|
wrappedList(targetPlanName),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
secondaryButton {
|
secondaryButton {
|
||||||
text = resourceReference(R.string.common_cancel)
|
text = resourceReference(R.string.common_cancel)
|
||||||
onClick { closeBs() }
|
onClick { closeBs() }
|
||||||
}
|
}
|
||||||
primaryButton {
|
primaryButton {
|
||||||
text = stringReference("Stay on $planName")
|
text = resourceReference(R.string.tangempay_current_plan_stay_button, wrappedList(planName))
|
||||||
onClick {
|
onClick {
|
||||||
onStayClick()
|
onStayClick()
|
||||||
closeBs()
|
closeBs()
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package com.tangem.features.tangempay.cashback.impl.model
|
||||||
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
import com.tangem.domain.models.account.TangemPayTariffPlan
|
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
internal class TangemPayCashbackDetailsConverterTest {
|
internal class TangemPayCashbackDetailsConverterTest {
|
||||||
|
|
@ -81,7 +80,7 @@ internal class TangemPayCashbackDetailsConverterTest {
|
||||||
min: String? = null,
|
min: String? = null,
|
||||||
cap: String? = null,
|
cap: String? = null,
|
||||||
) = CashbackTier(
|
) = CashbackTier(
|
||||||
planType = TangemPayTariffPlan.Type.UNKNOWN,
|
tierId = "basic",
|
||||||
rate = rate,
|
rate = rate,
|
||||||
label = label,
|
label = label,
|
||||||
scope = scope,
|
scope = scope,
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ internal class TangemPayCashbackInfoTilesConverterTest {
|
||||||
@MethodSource("rateSelectionModels")
|
@MethodSource("rateSelectionModels")
|
||||||
fun `GIVEN plan WHEN convert THEN rate tile shows the tier rate and the plan subtitle`(model: RateSelectionModel) {
|
fun `GIVEN plan WHEN convert THEN rate tile shows the tier rate and the plan subtitle`(model: RateSelectionModel) {
|
||||||
// Act
|
// Act
|
||||||
val result = converter.convert(twoTiers(), model.plan, model.planName)
|
val result = converter.convert(twoTiers(), model.plan)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertThat(result.rate.title).isEqualTo(stringReference(model.expectedTitle))
|
assertThat(result.rate.title).isEqualTo(stringReference(model.expectedTitle))
|
||||||
|
|
@ -29,9 +29,9 @@ internal class TangemPayCashbackInfoTilesConverterTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `GIVEN empty tiers and unknown plan WHEN convert THEN rate tile has no percent and empty subtitle`() {
|
fun `GIVEN empty tiers and no plan WHEN convert THEN rate tile has no percent and empty subtitle`() {
|
||||||
// Act
|
// Act
|
||||||
val result = converter.convert(emptyList(), TangemPayTariffPlan.Type.UNKNOWN, currentPlanName = null)
|
val result = converter.convert(emptyList(), currentPlan = null)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertThat(result.rate.title).isEqualTo(stringReference("Cashback"))
|
assertThat(result.rate.title).isEqualTo(stringReference("Cashback"))
|
||||||
|
|
@ -41,7 +41,7 @@ internal class TangemPayCashbackInfoTilesConverterTest {
|
||||||
@Test
|
@Test
|
||||||
fun `GIVEN any tiers WHEN convert THEN accruals tile is static`() {
|
fun `GIVEN any tiers WHEN convert THEN accruals tile is static`() {
|
||||||
// Act
|
// Act
|
||||||
val result = converter.convert(twoTiers(), TangemPayTariffPlan.Type.BASIC, currentPlanName = "Basic")
|
val result = converter.convert(twoTiers(), plan(tierId = "basic", name = "Basic"))
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assertThat(result.accruals.title).isEqualTo(stringReference("Accruals"))
|
assertThat(result.accruals.title).isEqualTo(stringReference("Accruals"))
|
||||||
|
|
@ -50,43 +50,52 @@ internal class TangemPayCashbackInfoTilesConverterTest {
|
||||||
|
|
||||||
private fun rateSelectionModels() = listOf(
|
private fun rateSelectionModels() = listOf(
|
||||||
RateSelectionModel(
|
RateSelectionModel(
|
||||||
plan = TangemPayTariffPlan.Type.PLUS,
|
plan = plan(tierId = "plus", name = "Plus"),
|
||||||
planName = "Plus",
|
|
||||||
expectedTitle = "Cashback 2%",
|
expectedTitle = "Cashback 2%",
|
||||||
expectedSubtitle = stringReference("With your Plus plan"),
|
expectedSubtitle = stringReference("With your Plus plan"),
|
||||||
),
|
),
|
||||||
RateSelectionModel(
|
RateSelectionModel(
|
||||||
plan = TangemPayTariffPlan.Type.BASIC,
|
plan = plan(tierId = "basic", name = "Basic"),
|
||||||
planName = "Basic",
|
|
||||||
expectedTitle = "Cashback 1%",
|
expectedTitle = "Cashback 1%",
|
||||||
expectedSubtitle = stringReference("With your Basic plan"),
|
expectedSubtitle = stringReference("With your Basic plan"),
|
||||||
),
|
),
|
||||||
RateSelectionModel(
|
RateSelectionModel(
|
||||||
plan = TangemPayTariffPlan.Type.UNKNOWN,
|
plan = plan(tierId = "gold", name = "Gold"),
|
||||||
planName = null,
|
expectedTitle = "Cashback 1%",
|
||||||
|
expectedSubtitle = stringReference("With your Gold plan"),
|
||||||
|
),
|
||||||
|
RateSelectionModel(
|
||||||
|
plan = null,
|
||||||
expectedTitle = "Cashback 1%",
|
expectedTitle = "Cashback 1%",
|
||||||
expectedSubtitle = TextReference.EMPTY,
|
expectedSubtitle = TextReference.EMPTY,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun twoTiers() = listOf(
|
private fun twoTiers() = listOf(
|
||||||
tier(TangemPayTariffPlan.Type.BASIC, rate = 1),
|
tier(tierId = "basic", rate = 1),
|
||||||
tier(TangemPayTariffPlan.Type.PLUS, rate = 2),
|
tier(tierId = "plus", rate = 2),
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun tier(planType: TangemPayTariffPlan.Type = TangemPayTariffPlan.Type.UNKNOWN, rate: Int? = null) =
|
private fun tier(tierId: String, rate: Int? = null) = CashbackTier(
|
||||||
CashbackTier(
|
tierId = tierId,
|
||||||
planType = planType,
|
rate = rate,
|
||||||
rate = rate,
|
label = "label",
|
||||||
label = "label",
|
scope = "scope",
|
||||||
scope = "scope",
|
minPurchase = null,
|
||||||
minPurchase = null,
|
monthlyCap = null,
|
||||||
monthlyCap = null,
|
)
|
||||||
)
|
|
||||||
|
private fun plan(tierId: String, name: String) = TangemPayTariffPlan(
|
||||||
|
id = "plan-$tierId",
|
||||||
|
tierId = tierId,
|
||||||
|
isBasicTier = tierId == "basic",
|
||||||
|
name = name,
|
||||||
|
programName = "program",
|
||||||
|
descriptionItems = emptyList(),
|
||||||
|
)
|
||||||
|
|
||||||
data class RateSelectionModel(
|
data class RateSelectionModel(
|
||||||
val plan: TangemPayTariffPlan.Type,
|
val plan: TangemPayTariffPlan?,
|
||||||
val planName: String?,
|
|
||||||
val expectedTitle: String,
|
val expectedTitle: String,
|
||||||
val expectedSubtitle: TextReference,
|
val expectedSubtitle: TextReference,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ internal class TangemPayCashbackModelTest {
|
||||||
coEvery { cashbackRepository.getCashbackPromotions(any()) } returns promotions().right()
|
coEvery { cashbackRepository.getCashbackPromotions(any()) } returns promotions().right()
|
||||||
coEvery { cashbackRepository.getCashbackAccrualDocs(any()) } returns docs().right()
|
coEvery { cashbackRepository.getCashbackAccrualDocs(any()) } returns docs().right()
|
||||||
coEvery { onboardingRepository.getCustomerInfo(any()) } returns
|
coEvery { onboardingRepository.getCustomerInfo(any()) } returns
|
||||||
customerInfo(TangemPayTariffPlan.Type.BASIC).right()
|
customerInfo(tierId = "basic", planName = "Basic").right()
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
|
|
@ -69,7 +69,7 @@ internal class TangemPayCashbackModelTest {
|
||||||
fun `GIVEN PLUS plan WHEN model created THEN rate tile shows the Plus tier rate`() {
|
fun `GIVEN PLUS plan WHEN model created THEN rate tile shows the Plus tier rate`() {
|
||||||
// Arrange
|
// Arrange
|
||||||
coEvery { onboardingRepository.getCustomerInfo(any()) } returns
|
coEvery { onboardingRepository.getCustomerInfo(any()) } returns
|
||||||
customerInfo(TangemPayTariffPlan.Type.PLUS).right()
|
customerInfo(tierId = "plus", planName = "Plus").right()
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
val model = createModel()
|
val model = createModel()
|
||||||
|
|
@ -162,12 +162,16 @@ internal class TangemPayCashbackModelTest {
|
||||||
CashbackDocument(id = "terms", title = "Full terms of cashback program", url = "https://x/terms.pdf"),
|
CashbackDocument(id = "terms", title = "Full terms of cashback program", url = "https://x/terms.pdf"),
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun customerInfo(planType: TangemPayTariffPlan.Type): CustomerInfo {
|
private fun customerInfo(tierId: String, planName: String): CustomerInfo {
|
||||||
val tariffPlanMock = mockk<TangemPayTariffPlan> {
|
val currentPlan = TangemPayTariffPlan(
|
||||||
every { type } returns planType
|
id = "plan-$tierId",
|
||||||
every { name } returns planType.name
|
tierId = tierId,
|
||||||
}
|
isBasicTier = tierId == "basic",
|
||||||
val customerTariffPlanMock = mockk<TangemPayCustomerTariffPlan> { every { plan } returns tariffPlanMock }
|
name = planName,
|
||||||
|
programName = "program",
|
||||||
|
descriptionItems = emptyList(),
|
||||||
|
)
|
||||||
|
val customerTariffPlanMock = mockk<TangemPayCustomerTariffPlan> { every { plan } returns currentPlan }
|
||||||
return mockk { every { tariffPlan } returns customerTariffPlanMock }
|
return mockk { every { tariffPlan } returns customerTariffPlanMock }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package com.tangem.features.tangempay.cashback.impl.model
|
package com.tangem.features.tangempay.cashback.impl.model
|
||||||
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import com.tangem.domain.models.account.TangemPayTariffPlan
|
|
||||||
import com.tangem.domain.pay.model.CashbackPromotions
|
import com.tangem.domain.pay.model.CashbackPromotions
|
||||||
import org.junit.jupiter.api.AfterEach
|
import org.junit.jupiter.api.AfterEach
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
|
@ -38,7 +37,7 @@ internal class TangemPayCashbackTiersConverterTest {
|
||||||
// Assert
|
// Assert
|
||||||
assertThat(result).containsExactly(
|
assertThat(result).containsExactly(
|
||||||
CashbackTier(
|
CashbackTier(
|
||||||
planType = TangemPayTariffPlan.Type.BASIC,
|
tierId = "basic",
|
||||||
rate = 1,
|
rate = 1,
|
||||||
label = "Basic cards",
|
label = "Basic cards",
|
||||||
scope = "All purchases",
|
scope = "All purchases",
|
||||||
|
|
@ -46,7 +45,7 @@ internal class TangemPayCashbackTiersConverterTest {
|
||||||
monthlyCap = "$100",
|
monthlyCap = "$100",
|
||||||
),
|
),
|
||||||
CashbackTier(
|
CashbackTier(
|
||||||
planType = TangemPayTariffPlan.Type.PLUS,
|
tierId = "plus",
|
||||||
rate = 2,
|
rate = 2,
|
||||||
label = "Plus cards",
|
label = "Plus cards",
|
||||||
scope = "Everywhere",
|
scope = "Everywhere",
|
||||||
|
|
@ -57,7 +56,7 @@ internal class TangemPayCashbackTiersConverterTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `GIVEN unknown tier WHEN convert THEN rate null and plan type UNKNOWN`() {
|
fun `GIVEN unknown tier WHEN convert THEN rate is null and tier id kept`() {
|
||||||
// Arrange
|
// Arrange
|
||||||
val promotions = promotions(tier(id = "gold", label = "Gold", scope = "All", min = null, cap = null))
|
val promotions = promotions(tier(id = "gold", label = "Gold", scope = "All", min = null, cap = null))
|
||||||
|
|
||||||
|
|
@ -67,7 +66,7 @@ internal class TangemPayCashbackTiersConverterTest {
|
||||||
// Assert
|
// Assert
|
||||||
assertThat(result).containsExactly(
|
assertThat(result).containsExactly(
|
||||||
CashbackTier(
|
CashbackTier(
|
||||||
planType = TangemPayTariffPlan.Type.UNKNOWN,
|
tierId = "gold",
|
||||||
rate = null,
|
rate = null,
|
||||||
label = "Gold",
|
label = "Gold",
|
||||||
scope = "All",
|
scope = "All",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue