Labels
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
// [PACKAGE] com.homebox.lens.data.api
|
||||
// [FILE] HomeboxApiService.kt
|
||||
|
||||
package com.homebox.lens.data.api
|
||||
|
||||
import com.homebox.lens.data.api.dto.GroupStatisticsDto
|
||||
@@ -8,7 +7,9 @@ import com.homebox.lens.data.api.dto.ItemCreateDto
|
||||
import com.homebox.lens.data.api.dto.ItemOutDto
|
||||
import com.homebox.lens.data.api.dto.ItemSummaryDto
|
||||
import com.homebox.lens.data.api.dto.ItemUpdateDto
|
||||
import com.homebox.lens.data.api.dto.LabelCreateDto
|
||||
import com.homebox.lens.data.api.dto.LabelOutDto
|
||||
import com.homebox.lens.data.api.dto.LabelSummaryDto
|
||||
import com.homebox.lens.data.api.dto.LocationOutCountDto
|
||||
import com.homebox.lens.data.api.dto.LoginFormDto
|
||||
import com.homebox.lens.data.api.dto.PaginationResultDto
|
||||
@@ -31,8 +32,6 @@ import retrofit2.http.Query
|
||||
interface HomeboxApiService {
|
||||
|
||||
// [ENDPOINT] Auth
|
||||
// [FIX] Явно указываем заголовок Content-Type, чтобы переопределить
|
||||
// значение по умолчанию от Moshi, которое содержит "; charset=UTF-8".
|
||||
@Headers("Content-Type: application/json")
|
||||
@POST("v1/users/login")
|
||||
suspend fun login(@Body loginForm: LoginFormDto): TokenResponseDto
|
||||
@@ -65,9 +64,11 @@ interface HomeboxApiService {
|
||||
@GET("v1/labels")
|
||||
suspend fun getLabels(): List<LabelOutDto>
|
||||
|
||||
@POST("v1/labels")
|
||||
suspend fun createLabel(@Body newLabel: LabelCreateDto): LabelSummaryDto
|
||||
|
||||
// [ENDPOINT] Statistics
|
||||
@GET("v1/groups/statistics")
|
||||
suspend fun getStatistics(): GroupStatisticsDto
|
||||
}
|
||||
|
||||
// [END_FILE_HomeboxApiService.kt]
|
||||
// [END_FILE_HomeboxApiService.kt]
|
||||
@@ -19,7 +19,7 @@ data class ItemOut(
|
||||
@Json(name = "description") val description: String?,
|
||||
@Json(name = "image") val image: String?,
|
||||
@Json(name = "location") val location: LocationOut?,
|
||||
@Json(name = "labels") val labels: List<LabelOut>,
|
||||
@Json(name = "labels") val labels: List<LabelOutDto>,
|
||||
@Json(name = "value") val value: BigDecimal?,
|
||||
@Json(name = "createdAt") val createdAt: String?
|
||||
)
|
||||
|
||||
@@ -1,4 +1,23 @@
|
||||
// [PACKAGE] com.homebox.lens.data.api.dto
|
||||
// [FILE] LabelCreateDto.kt
|
||||
// [SEMANTICS] data_transfer_object, label, create, api
|
||||
package com.homebox.lens.data.api.dto
|
||||
|
||||
class LabelCreateDto {
|
||||
}
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* [CONTRACT]
|
||||
* DTO для тела запроса на создание метки (POST /v1/labels).
|
||||
* @property name Название метки.
|
||||
* @property color Цвет метки в формате HEX (например, "#FF0000").
|
||||
* @property description Описание метки.
|
||||
* @coherence_note Структура этого класса точно соответствует схеме `repo.LabelCreate` из OpenAPI.
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class LabelCreateDto(
|
||||
@Json(name = "name") val name: String,
|
||||
@Json(name = "color") val color: String?,
|
||||
@Json(name = "description") val description: String? = null // Описание не используется в приложении, но может быть в API
|
||||
)
|
||||
// [END_FILE_LabelCreateDto.kt]
|
||||
@@ -0,0 +1,38 @@
|
||||
// [PACKAGE] com.homebox.lens.data.api.dto
|
||||
// [FILE] LabelSummaryDto.kt
|
||||
// [SEMANTICS] data_transfer_object, label, summary, api, mapper
|
||||
package com.homebox.lens.data.api.dto
|
||||
|
||||
import com.homebox.lens.domain.model.LabelSummary
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
/**
|
||||
* [CONTRACT]
|
||||
* DTO для ответа от API при создании метки.
|
||||
* @coherence_note Структура этого класса точно соответствует схеме `repo.LabelSummary` из OpenAPI.
|
||||
*/
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class LabelSummaryDto(
|
||||
@Json(name = "id") val id: String,
|
||||
@Json(name = "name") val name: String,
|
||||
@Json(name = "color") val color: String?,
|
||||
@Json(name = "description") val description: String?,
|
||||
@Json(name = "createdAt") val createdAt: String?,
|
||||
@Json(name = "updatedAt") val updatedAt: String?
|
||||
)
|
||||
|
||||
/**
|
||||
* [CONTRACT]
|
||||
* @summary Маппер из DTO в доменную модель.
|
||||
* @return Объект доменной модели [LabelSummary].
|
||||
* @sideeffect Отбрасывает поля, ненужные доменному слою (`color`, `description`, etc.),
|
||||
* оставляя только `id` и `name`.
|
||||
*/
|
||||
fun LabelSummaryDto.toDomain(): LabelSummary {
|
||||
return LabelSummary(
|
||||
id = this.id,
|
||||
name = this.name
|
||||
)
|
||||
}
|
||||
// [END_FILE_LabelSummaryDto.kt]
|
||||
@@ -1,11 +1,10 @@
|
||||
// [PACKAGE] com.homebox.lens.data.repository
|
||||
// [FILE] ItemRepositoryImpl.kt
|
||||
// [SEMANTICS] data_repository, implementation, items
|
||||
|
||||
// [SEMANTICS] data_repository, implementation, items, labels
|
||||
package com.homebox.lens.data.repository
|
||||
|
||||
// [IMPORTS]
|
||||
import com.homebox.lens.data.api.HomeboxApiService
|
||||
import com.homebox.lens.data.api.dto.LabelCreateDto
|
||||
import com.homebox.lens.data.api.dto.toDomain
|
||||
import com.homebox.lens.data.api.dto.toDto
|
||||
import com.homebox.lens.data.db.dao.ItemDao
|
||||
@@ -16,99 +15,95 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
// [CORE-LOGIC]
|
||||
/**
|
||||
* [CONTRACT]
|
||||
* Реализация репозитория для работы с данными о вещах.
|
||||
* @param apiService Сервис для взаимодействия с Homebox API.
|
||||
* @param itemDao DAO для доступа к локальной базе данных.
|
||||
* [COHERENCE_NOTE] Метод 'login' был полностью удален из этого класса, так как его ответственность
|
||||
* была передана в AuthRepositoryImpl. Это устраняет ошибку компиляции "'login' overrides nothing".
|
||||
[CONTRACT]
|
||||
Реализация репозитория для работы с данными о вещах.
|
||||
@param apiService Сервис для взаимодействия с Homebox API.
|
||||
@param itemDao DAO для доступа к локальной базе данных.
|
||||
*/
|
||||
@Singleton
|
||||
class ItemRepositoryImpl @Inject constructor(
|
||||
private val apiService: HomeboxApiService,
|
||||
private val itemDao: ItemDao
|
||||
) : ItemRepository {
|
||||
|
||||
// [DELETED] Метод login был здесь, но теперь он удален.
|
||||
|
||||
/**
|
||||
* [CONTRACT] @see ItemRepository.createItem
|
||||
[CONTRACT] @see ItemRepository.createItem
|
||||
*/
|
||||
override suspend fun createItem(newItemData: ItemCreate): ItemSummary {
|
||||
val itemDto = newItemData.toDto()
|
||||
val resultDto = apiService.createItem(itemDto)
|
||||
return resultDto.toDomain()
|
||||
}
|
||||
|
||||
/**
|
||||
* [CONTRACT] @see ItemRepository.getItemDetails
|
||||
[CONTRACT] @see ItemRepository.getItemDetails
|
||||
*/
|
||||
override suspend fun getItemDetails(itemId: String): ItemOut {
|
||||
val resultDto = apiService.getItem(itemId)
|
||||
return resultDto.toDomain()
|
||||
}
|
||||
|
||||
/**
|
||||
* [CONTRACT] @see ItemRepository.updateItem
|
||||
[CONTRACT] @see ItemRepository.updateItem
|
||||
*/
|
||||
override suspend fun updateItem(itemId: String, item: ItemUpdate): ItemOut {
|
||||
val itemDto = item.toDto()
|
||||
val resultDto = apiService.updateItem(itemId, itemDto)
|
||||
return resultDto.toDomain()
|
||||
}
|
||||
|
||||
/**
|
||||
* [CONTRACT] @see ItemRepository.deleteItem
|
||||
[CONTRACT] @see ItemRepository.deleteItem
|
||||
*/
|
||||
override suspend fun deleteItem(itemId: String) {
|
||||
apiService.deleteItem(itemId)
|
||||
}
|
||||
|
||||
/**
|
||||
* [CONTRACT] @see ItemRepository.syncInventory
|
||||
[CONTRACT] @see ItemRepository.syncInventory
|
||||
*/
|
||||
override suspend fun syncInventory(page: Int, pageSize: Int): PaginationResult<ItemSummary> {
|
||||
val resultDto = apiService.getItems(page = page, pageSize = pageSize)
|
||||
return resultDto.toDomain { it.toDomain() }
|
||||
}
|
||||
|
||||
/**
|
||||
* [CONTRACT] @see ItemRepository.getStatistics
|
||||
[CONTRACT] @see ItemRepository.getStatistics
|
||||
*/
|
||||
override suspend fun getStatistics(): GroupStatistics {
|
||||
val resultDto = apiService.getStatistics()
|
||||
return resultDto.toDomain()
|
||||
}
|
||||
|
||||
/**
|
||||
* [CONTRACT] @see ItemRepository.getAllLocations
|
||||
[CONTRACT] @see ItemRepository.getAllLocations
|
||||
*/
|
||||
override suspend fun getAllLocations(): List<LocationOutCount> {
|
||||
val resultDto = apiService.getLocations()
|
||||
return resultDto.map { it.toDomain() }
|
||||
}
|
||||
|
||||
/**
|
||||
* [CONTRACT] @see ItemRepository.getAllLabels
|
||||
[CONTRACT] @see ItemRepository.getAllLabels
|
||||
*/
|
||||
override suspend fun getAllLabels(): List<LabelOut> {
|
||||
val resultDto = apiService.getLabels()
|
||||
return resultDto.map { it.toDomain() }
|
||||
}
|
||||
|
||||
/**
|
||||
* [CONTRACT] @see ItemRepository.searchItems
|
||||
[CONTRACT] @see ItemRepository.createLabel
|
||||
*/
|
||||
override suspend fun createLabel(newLabelData: LabelCreate): LabelSummary {
|
||||
// [DATA-FLOW] Convert domain model to DTO for the API call.
|
||||
val labelCreateDto = newLabelData.toDto()
|
||||
// [ACTION] Call the API service.
|
||||
val resultDto = apiService.createLabel(labelCreateDto)
|
||||
// [DATA-FLOW] Convert the resulting DTO back to a domain model.
|
||||
return resultDto.toDomain()
|
||||
}
|
||||
/**
|
||||
[CONTRACT] @see ItemRepository.searchItems
|
||||
*/
|
||||
override suspend fun searchItems(query: String): PaginationResult<ItemSummary> {
|
||||
val resultDto = apiService.getItems(query = query)
|
||||
return resultDto.toDomain { it.toDomain() }
|
||||
}
|
||||
|
||||
/**
|
||||
* [CONTRACT] @see ItemRepository.getRecentlyAddedItems
|
||||
[CONTRACT] @see ItemRepository.getRecentlyAddedItems
|
||||
*/
|
||||
override fun getRecentlyAddedItems(limit: Int): Flow<List<ItemSummary>> {
|
||||
return itemDao.getRecentlyAddedItems(limit).map { entities ->
|
||||
@@ -116,4 +111,17 @@ class ItemRepositoryImpl @Inject constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
// [HELPER] Mapper function for LabelCreate
|
||||
/**
|
||||
[CONTRACT]
|
||||
@summary Маппер из доменной модели LabelCreate в DTO LabelCreateDto.
|
||||
@return DTO-объект [LabelCreateDto].
|
||||
*/
|
||||
private fun LabelCreate.toDto(): LabelCreateDto {
|
||||
return LabelCreateDto(
|
||||
name = this.name,
|
||||
color = this.color,
|
||||
description = null // Description is not part of the domain model for creation.
|
||||
)
|
||||
}
|
||||
// [END_FILE_ItemRepositoryImpl.kt]
|
||||
Reference in New Issue
Block a user