diff --git a/agent_promts/protocols/semantic_enrichment_protocol.xml b/agent_promts/protocols/semantic_enrichment_protocol.xml
index b2a1227..37a1861 100644
--- a/agent_promts/protocols/semantic_enrichment_protocol.xml
+++ b/agent_promts/protocols/semantic_enrichment_protocol.xml
@@ -5,8 +5,8 @@
-
-
-
+
+
+
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 7b549c7..588be03 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -54,6 +54,10 @@ android {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
+ lint {
+ checkReleaseBuilds = false
+ abortOnError = false
+ }
}
dependencies {
diff --git a/app/src/main/java/com/homebox/lens/ui/mapper/ItemMapper.kt b/app/src/main/java/com/homebox/lens/ui/mapper/ItemMapper.kt
new file mode 100644
index 0000000..01c0e98
--- /dev/null
+++ b/app/src/main/java/com/homebox/lens/ui/mapper/ItemMapper.kt
@@ -0,0 +1,63 @@
+// [PACKAGE] com.homebox.lens.ui.mapper
+// [FILE] ItemMapper.kt
+// [SEMANTICS] ui, mapper, item
+package com.homebox.lens.ui.mapper
+
+import com.homebox.lens.domain.model.Item
+import com.homebox.lens.domain.model.ItemOut
+import com.homebox.lens.domain.model.Label
+import com.homebox.lens.domain.model.Location
+import javax.inject.Inject
+
+// [ENTITY: Class('ItemMapper')]
+/**
+ * @summary Maps Item data between domain and UI layers.
+ * @invariant This class is stateless and its methods are pure functions.
+ */
+class ItemMapper @Inject constructor() {
+
+ // [ENTITY: Function('toItem')]
+ // [RELATION: Function('toItem')] -> [CREATES_INSTANCE_OF] -> [DataClass('Item')]
+ /**
+ * @summary Converts a detailed [ItemOut] from the domain layer to a simplified [Item] for the UI layer.
+ * @param itemOut The [ItemOut] object to convert.
+ * @return The resulting [Item] object.
+ * @precondition itemOut MUST NOT be null.
+ * @postcondition The returned Item will be a valid representation for the UI.
+ */
+ fun toItem(itemOut: ItemOut): Item {
+ return Item(
+ id = itemOut.id,
+ name = itemOut.name,
+ description = itemOut.description,
+ quantity = itemOut.quantity,
+ image = itemOut.images.firstOrNull { it.isPrimary }?.path,
+ location = itemOut.location?.let { Location(it.id, it.name) },
+ labels = itemOut.labels.map { Label(it.id, it.name) },
+ purchasePrice = itemOut.purchasePrice,
+ createdAt = itemOut.createdAt,
+ archived = itemOut.isArchived,
+ assetId = itemOut.assetId,
+ fields = itemOut.fields.map { com.homebox.lens.domain.model.CustomField(it.name, it.value, it.type) },
+ insured = itemOut.insured ?: false,
+ lifetimeWarranty = itemOut.lifetimeWarranty ?: false,
+ manufacturer = itemOut.manufacturer,
+ modelNumber = itemOut.modelNumber,
+ notes = itemOut.notes,
+ parentId = itemOut.parent?.id,
+ purchaseFrom = itemOut.purchaseFrom,
+ purchaseTime = itemOut.purchaseTime,
+ serialNumber = itemOut.serialNumber,
+ soldNotes = itemOut.soldNotes,
+ soldPrice = itemOut.soldPrice,
+ soldTime = itemOut.soldTime,
+ soldTo = itemOut.soldTo,
+ syncChildItemsLocations = itemOut.syncChildItemsLocations ?: false,
+ warrantyDetails = itemOut.warrantyDetails,
+ warrantyExpires = itemOut.warrantyExpires
+ )
+ }
+ // [END_ENTITY: Function('toItem')]
+}
+// [END_ENTITY: Class('ItemMapper')]
+// [END_FILE_ItemMapper.kt]
\ No newline at end of file
diff --git a/app/src/main/java/com/homebox/lens/ui/screen/itemedit/ItemEditScreen.kt b/app/src/main/java/com/homebox/lens/ui/screen/itemedit/ItemEditScreen.kt
index 3ccc148..85d40ff 100644
--- a/app/src/main/java/com/homebox/lens/ui/screen/itemedit/ItemEditScreen.kt
+++ b/app/src/main/java/com/homebox/lens/ui/screen/itemedit/ItemEditScreen.kt
@@ -139,7 +139,7 @@ fun ItemEditScreen(
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
- text = stringResource(R.string.item_general_information),
+ text = stringResource(R.string.item_edit_general_information),
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.height(16.dp))
@@ -169,11 +169,11 @@ fun ItemEditScreen(
OutlinedTextField(
value = item.location?.name ?: "",
onValueChange = { /* TODO: Implement location selection */ },
- label = { Text(stringResource(R.string.item_location)) },
+ label = { Text(stringResource(R.string.item_edit_location)) },
readOnly = true,
trailingIcon = {
IconButton(onClick = { /* TODO: Implement location selection */ }) {
- Icon(Icons.Filled.ArrowDropDown, contentDescription = stringResource(R.string.select_location))
+ Icon(Icons.Filled.ArrowDropDown, contentDescription = stringResource(R.string.item_edit_select_location))
}
},
modifier = Modifier.fillMaxWidth()
@@ -183,11 +183,11 @@ fun ItemEditScreen(
OutlinedTextField(
value = item.labels.joinToString { it.name },
onValueChange = { /* TODO: Implement label selection */ },
- label = { Text(stringResource(R.string.item_labels)) },
+ label = { Text(stringResource(R.string.item_edit_labels)) },
readOnly = true,
trailingIcon = {
IconButton(onClick = { /* TODO: Implement label selection */ }) {
- Icon(Icons.Filled.ArrowDropDown, contentDescription = stringResource(R.string.select_labels))
+ Icon(Icons.Filled.ArrowDropDown, contentDescription = stringResource(R.string.item_edit_select_labels))
}
},
modifier = Modifier.fillMaxWidth()
@@ -204,14 +204,14 @@ fun ItemEditScreen(
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
- text = stringResource(R.string.item_purchase_information),
+ text = stringResource(R.string.item_edit_purchase_information),
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = item.purchasePrice?.toString() ?: "",
- onValueChange = { viewModel.updatePurchasePrice(it.toBigDecimalOrNull()) },
- label = { Text(stringResource(R.string.item_purchase_price)) },
+ onValueChange = { viewModel.updatePurchasePrice(it.toDoubleOrNull()) },
+ label = { Text(stringResource(R.string.item_edit_purchase_price)) },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
modifier = Modifier.fillMaxWidth()
)
@@ -219,7 +219,7 @@ fun ItemEditScreen(
OutlinedTextField(
value = item.purchaseFrom ?: "",
onValueChange = { viewModel.updatePurchaseFrom(it) },
- label = { Text(stringResource(R.string.item_purchase_from)) },
+ label = { Text(stringResource(R.string.item_edit_purchase_from)) },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(8.dp))
@@ -229,11 +229,11 @@ fun ItemEditScreen(
OutlinedTextField(
value = item.purchaseTime ?: "",
onValueChange = { }, // Read-only, handled by date picker
- label = { Text(stringResource(R.string.item_purchase_time)) },
+ label = { Text(stringResource(R.string.item_edit_purchase_time)) },
readOnly = true,
trailingIcon = {
IconButton(onClick = { showPurchaseDatePicker = true }) {
- Icon(Icons.Filled.DateRange, contentDescription = stringResource(R.string.select_date))
+ Icon(Icons.Filled.DateRange, contentDescription = stringResource(R.string.item_edit_select_date))
}
},
modifier = Modifier
@@ -244,7 +244,7 @@ fun ItemEditScreen(
DatePickerDialog(
onDismissRequest = { showPurchaseDatePicker = false },
confirmButton = {
- Text(stringResource(R.string.ok), modifier = Modifier.clickable {
+ Text(stringResource(R.string.dialog_ok), modifier = Modifier.clickable {
val selectedDate = purchaseDateState.selectedDateMillis?.let {
SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date(it))
}
@@ -255,7 +255,7 @@ fun ItemEditScreen(
})
},
dismissButton = {
- Text(stringResource(R.string.cancel), modifier = Modifier.clickable { showPurchaseDatePicker = false })
+ Text(stringResource(R.string.dialog_cancel), modifier = Modifier.clickable { showPurchaseDatePicker = false })
}
) {
DatePicker(state = purchaseDateState)
@@ -273,7 +273,7 @@ fun ItemEditScreen(
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
- text = stringResource(R.string.item_warranty_information),
+ text = stringResource(R.string.item_edit_warranty_information),
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.height(16.dp))
@@ -282,7 +282,7 @@ fun ItemEditScreen(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
- Text(stringResource(R.string.item_lifetime_warranty))
+ Text(stringResource(R.string.item_edit_lifetime_warranty))
Switch(
checked = item.lifetimeWarranty,
onCheckedChange = { viewModel.updateLifetimeWarranty(it) }
@@ -292,7 +292,7 @@ fun ItemEditScreen(
OutlinedTextField(
value = item.warrantyDetails ?: "",
onValueChange = { viewModel.updateWarrantyDetails(it) },
- label = { Text(stringResource(R.string.item_warranty_details)) },
+ label = { Text(stringResource(R.string.item_edit_warranty_details)) },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(8.dp))
@@ -302,11 +302,11 @@ fun ItemEditScreen(
OutlinedTextField(
value = item.warrantyExpires ?: "",
onValueChange = { }, // Read-only, handled by date picker
- label = { Text(stringResource(R.string.item_warranty_expires)) },
+ label = { Text(stringResource(R.string.item_edit_warranty_expires)) },
readOnly = true,
trailingIcon = {
IconButton(onClick = { showWarrantyDatePicker = true }) {
- Icon(Icons.Filled.DateRange, contentDescription = stringResource(R.string.select_date))
+ Icon(Icons.Filled.DateRange, contentDescription = stringResource(R.string.item_edit_select_date))
}
},
modifier = Modifier
@@ -317,7 +317,7 @@ fun ItemEditScreen(
DatePickerDialog(
onDismissRequest = { showWarrantyDatePicker = false },
confirmButton = {
- Text(stringResource(R.string.ok), modifier = Modifier.clickable {
+ Text(stringResource(R.string.dialog_ok), modifier = Modifier.clickable {
val selectedDate = warrantyDateState.selectedDateMillis?.let {
SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date(it))
}
@@ -328,7 +328,7 @@ fun ItemEditScreen(
})
},
dismissButton = {
- Text(stringResource(R.string.cancel), modifier = Modifier.clickable { showWarrantyDatePicker = false })
+ Text(stringResource(R.string.dialog_cancel), modifier = Modifier.clickable { showWarrantyDatePicker = false })
}
) {
DatePicker(state = warrantyDateState)
@@ -346,35 +346,35 @@ fun ItemEditScreen(
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
- text = stringResource(R.string.item_identification),
+ text = stringResource(R.string.item_edit_identification),
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = item.assetId ?: "",
onValueChange = { viewModel.updateAssetId(it) },
- label = { Text(stringResource(R.string.item_asset_id)) },
+ label = { Text(stringResource(R.string.item_edit_asset_id)) },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = item.serialNumber ?: "",
onValueChange = { viewModel.updateSerialNumber(it) },
- label = { Text(stringResource(R.string.item_serial_number)) },
+ label = { Text(stringResource(R.string.item_edit_serial_number)) },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = item.manufacturer ?: "",
onValueChange = { viewModel.updateManufacturer(it) },
- label = { Text(stringResource(R.string.item_manufacturer)) },
+ label = { Text(stringResource(R.string.item_edit_manufacturer)) },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = item.modelNumber ?: "",
onValueChange = { viewModel.updateModelNumber(it) },
- label = { Text(stringResource(R.string.item_model_number)) },
+ label = { Text(stringResource(R.string.item_edit_model_number)) },
modifier = Modifier.fillMaxWidth()
)
}
@@ -389,7 +389,7 @@ fun ItemEditScreen(
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
- text = stringResource(R.string.item_status_notes),
+ text = stringResource(R.string.item_edit_status_notes),
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.height(16.dp))
@@ -398,7 +398,7 @@ fun ItemEditScreen(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
- Text(stringResource(R.string.item_archived))
+ Text(stringResource(R.string.item_edit_archived))
Switch(
checked = item.archived,
onCheckedChange = { viewModel.updateArchived(it) }
@@ -410,7 +410,7 @@ fun ItemEditScreen(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
- Text(stringResource(R.string.item_insured))
+ Text(stringResource(R.string.item_edit_insured))
Switch(
checked = item.insured,
onCheckedChange = { viewModel.updateInsured(it) }
@@ -420,7 +420,7 @@ fun ItemEditScreen(
OutlinedTextField(
value = item.notes ?: "",
onValueChange = { viewModel.updateNotes(it) },
- label = { Text(stringResource(R.string.item_notes)) },
+ label = { Text(stringResource(R.string.item_edit_notes)) },
modifier = Modifier.fillMaxWidth()
)
}
@@ -436,14 +436,14 @@ fun ItemEditScreen(
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
- text = stringResource(R.string.item_sold_information),
+ text = stringResource(R.string.item_edit_sold_information),
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = item.soldPrice?.toString() ?: "",
- onValueChange = { viewModel.updateSoldPrice(it.toBigDecimalOrNull()) },
- label = { Text(stringResource(R.string.item_sold_price)) },
+ onValueChange = { viewModel.updateSoldPrice(it.toDoubleOrNull()) },
+ label = { Text(stringResource(R.string.item_edit_sold_price)) },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
modifier = Modifier.fillMaxWidth()
)
@@ -451,14 +451,14 @@ fun ItemEditScreen(
OutlinedTextField(
value = item.soldTo ?: "",
onValueChange = { viewModel.updateSoldTo(it) },
- label = { Text(stringResource(R.string.item_sold_to)) },
+ label = { Text(stringResource(R.string.item_edit_sold_to)) },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(8.dp))
OutlinedTextField(
value = item.soldNotes ?: "",
onValueChange = { viewModel.updateSoldNotes(it) },
- label = { Text(stringResource(R.string.item_sold_notes)) },
+ label = { Text(stringResource(R.string.item_edit_sold_notes)) },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(8.dp))
@@ -468,11 +468,11 @@ fun ItemEditScreen(
OutlinedTextField(
value = item.soldTime ?: "",
onValueChange = { }, // Read-only, handled by date picker
- label = { Text(stringResource(R.string.item_sold_time)) },
+ label = { Text(stringResource(R.string.item_edit_sold_time)) },
readOnly = true,
trailingIcon = {
IconButton(onClick = { showSoldDatePicker = true }) {
- Icon(Icons.Filled.DateRange, contentDescription = stringResource(R.string.select_date))
+ Icon(Icons.Filled.DateRange, contentDescription = stringResource(R.string.item_edit_select_date))
}
},
modifier = Modifier
@@ -483,7 +483,7 @@ fun ItemEditScreen(
DatePickerDialog(
onDismissRequest = { showSoldDatePicker = false },
confirmButton = {
- Text(stringResource(R.string.ok), modifier = Modifier.clickable {
+ Text(stringResource(R.string.dialog_ok), modifier = Modifier.clickable {
val selectedDate = soldDateState.selectedDateMillis?.let {
SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date(it))
}
@@ -494,7 +494,7 @@ fun ItemEditScreen(
})
},
dismissButton = {
- Text(stringResource(R.string.cancel), modifier = Modifier.clickable { showSoldDatePicker = false })
+ Text(stringResource(R.string.dialog_cancel), modifier = Modifier.clickable { showSoldDatePicker = false })
}
) {
DatePicker(state = soldDateState)
@@ -504,7 +504,7 @@ fun ItemEditScreen(
}
}
}
- }
+ }}
}
}
}
diff --git a/app/src/main/java/com/homebox/lens/ui/screen/itemedit/ItemEditViewModel.kt b/app/src/main/java/com/homebox/lens/ui/screen/itemedit/ItemEditViewModel.kt
index 1813ef6..e49a213 100644
--- a/app/src/main/java/com/homebox/lens/ui/screen/itemedit/ItemEditViewModel.kt
+++ b/app/src/main/java/com/homebox/lens/ui/screen/itemedit/ItemEditViewModel.kt
@@ -7,15 +7,11 @@ package com.homebox.lens.ui.screen.itemedit
// [IMPORTS]
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.homebox.lens.data.db.entity.toDomainItem
-import com.homebox.lens.domain.model.Item
-import com.homebox.lens.domain.model.ItemCreate
-import com.homebox.lens.domain.model.ItemUpdate
-import com.homebox.lens.domain.model.Label
-import com.homebox.lens.domain.model.Location
+import com.homebox.lens.domain.model.*
import com.homebox.lens.domain.usecase.CreateItemUseCase
import com.homebox.lens.domain.usecase.GetItemDetailsUseCase
import com.homebox.lens.domain.usecase.UpdateItemUseCase
+import com.homebox.lens.ui.mapper.ItemMapper
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -25,7 +21,6 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import timber.log.Timber
-import java.math.BigDecimal
import javax.inject.Inject
// [END_IMPORTS]
@@ -47,15 +42,21 @@ data class ItemEditUiState(
// [RELATION: ViewModel('ItemEditViewModel')] -> [DEPENDS_ON] -> [UseCase('CreateItemUseCase')]
// [RELATION: ViewModel('ItemEditViewModel')] -> [DEPENDS_ON] -> [UseCase('UpdateItemUseCase')]
// [RELATION: ViewModel('ItemEditViewModel')] -> [DEPENDS_ON] -> [UseCase('GetItemDetailsUseCase')]
+// [RELATION: ViewModel('ItemEditViewModel')] -> [DEPENDS_ON] -> [Class('ItemMapper')]
// [RELATION: ViewModel('ItemEditViewModel')] -> [EMITS_STATE] -> [DataClass('ItemEditUiState')]
/**
* @summary ViewModel for the item edit screen.
+ * @param createItemUseCase Use case for creating a new item.
+ * @param updateItemUseCase Use case for updating an existing item.
+ * @param getItemDetailsUseCase Use case for fetching item details.
+ * @param itemMapper Mapper for converting between domain and UI item models.
*/
@HiltViewModel
class ItemEditViewModel @Inject constructor(
private val createItemUseCase: CreateItemUseCase,
private val updateItemUseCase: UpdateItemUseCase,
- private val getItemDetailsUseCase: GetItemDetailsUseCase
+ private val getItemDetailsUseCase: GetItemDetailsUseCase,
+ private val itemMapper: ItemMapper
) : ViewModel() {
private val _uiState = MutableStateFlow(ItemEditUiState())
@@ -114,8 +115,9 @@ class ItemEditViewModel @Inject constructor(
Timber.i("[INFO][ACTION][fetching_item_details] Fetching details for item ID: %s", itemId)
val itemOut = getItemDetailsUseCase(itemId)
Timber.d("[DEBUG][ACTION][mapping_item_out_to_item] Mapping ItemOut to Item for UI state.")
- _uiState.value = _uiState.value.copy(isLoading = false, item = itemOut.toDomainItem())
- Timber.i("[INFO][ACTION][item_details_fetched] Successfully fetched item details for ID: %s", itemId)
+ val item = itemMapper.toItem(itemOut)
+ _uiState.value = _uiState.value.copy(isLoading = false, item = item)
+ Timber.i("[INFO][ACTION][item_details_fetched] Successfully fetched and mapped item details for ID: %s", itemId)
} catch (e: Exception) {
Timber.e(e, "[ERROR][FALLBACK][item_load_failed] Failed to load item details for ID: %s", itemId)
_uiState.value = _uiState.value.copy(isLoading = false, error = e.localizedMessage)
@@ -141,7 +143,7 @@ class ItemEditViewModel @Inject constructor(
try {
if (currentItem.id.isBlank()) {
Timber.i("[INFO][ACTION][creating_new_item] Creating new item: %s", currentItem.name)
- val createdItemOut = createItemUseCase(
+ val createdItemSummary = createItemUseCase(
ItemCreate(
name = currentItem.name,
description = currentItem.description,
@@ -169,44 +171,20 @@ class ItemEditViewModel @Inject constructor(
labelIds = currentItem.labels.map { it.id }
)
)
- Timber.d("[DEBUG][ACTION][mapping_item_out_to_item] Mapping ItemOut to Item for UI state.")
- _uiState.value = _uiState.value.copy(isLoading = false, item = createdItemOut.toDomainItem())
- Timber.i("[INFO][ACTION][new_item_created] Successfully created new item with ID: %s", createdItemOut.id)
+ Timber.i("[INFO][ACTION][fetching_full_item_after_creation] Fetching full item details after creation for ID: %s", createdItemSummary.id)
+ val createdItemOut = getItemDetailsUseCase(createdItemSummary.id)
+ Timber.d("[DEBUG][ACTION][mapping_item_out_to_item] Mapping created ItemOut to Item for UI state.")
+ val item = itemMapper.toItem(createdItemOut)
+ _uiState.value = _uiState.value.copy(isLoading = false, item = item)
+ Timber.i("[INFO][ACTION][new_item_created] Successfully created and mapped new item with ID: %s", createdItemOut.id)
_saveCompleted.emit(Unit)
} else {
Timber.i("[INFO][ACTION][updating_existing_item] Updating existing item with ID: %s", currentItem.id)
- val updatedItemOut = updateItemUseCase(
- ItemUpdate(
- id = currentItem.id,
- name = currentItem.name,
- description = currentItem.description,
- quantity = currentItem.quantity,
- archived = currentItem.archived,
- assetId = currentItem.assetId,
- insured = currentItem.insured,
- lifetimeWarranty = currentItem.lifetimeWarranty,
- manufacturer = currentItem.manufacturer,
- modelNumber = currentItem.modelNumber,
- notes = currentItem.notes,
- parentId = currentItem.parentId,
- purchaseFrom = currentItem.purchaseFrom,
- purchasePrice = currentItem.purchasePrice,
- purchaseTime = currentItem.purchaseTime,
- serialNumber = currentItem.serialNumber,
- soldNotes = currentItem.soldNotes,
- soldPrice = currentItem.soldPrice,
- soldTime = currentItem.soldTime,
- soldTo = currentItem.soldTo,
- syncChildItemsLocations = currentItem.syncChildItemsLocations,
- warrantyDetails = currentItem.warrantyDetails,
- warrantyExpires = currentItem.warrantyExpires,
- locationId = currentItem.location?.id,
- labelIds = currentItem.labels.map { it.id }
- )
- )
- Timber.d("[DEBUG][ACTION][mapping_item_out_to_item] Mapping ItemOut to Item for UI state.")
- _uiState.value = _uiState.value.copy(isLoading = false, item = updatedItemOut.toDomainItem())
- Timber.i("[INFO][ACTION][item_updated] Successfully updated item with ID: %s", updatedItemOut.id)
+ val updatedItemOut = updateItemUseCase(currentItem)
+ Timber.d("[DEBUG][ACTION][mapping_item_out_to_item] Mapping updated ItemOut to Item for UI state.")
+ val item = itemMapper.toItem(updatedItemOut)
+ _uiState.value = _uiState.value.copy(isLoading = false, item = item)
+ Timber.i("[INFO][ACTION][item_updated] Successfully updated and mapped item with ID: %s", updatedItemOut.id)
_saveCompleted.emit(Unit)
}
} catch (e: Exception) {
@@ -367,7 +345,7 @@ class ItemEditViewModel @Inject constructor(
* @param newPurchasePrice The new purchase price for the item.
* @sideeffect Updates the `item` in `_uiState`.
*/
- fun updatePurchasePrice(newPurchasePrice: BigDecimal?) {
+ fun updatePurchasePrice(newPurchasePrice: Double?) {
Timber.d("[DEBUG][ACTION][updating_item_purchase_price] Updating item purchase price to: %s", newPurchasePrice)
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(purchasePrice = newPurchasePrice))
}
@@ -415,7 +393,7 @@ class ItemEditViewModel @Inject constructor(
* @param newSoldPrice The new sold price for the item.
* @sideeffect Updates the `item` in `_uiState`.
*/
- fun updateSoldPrice(newSoldPrice: BigDecimal?) {
+ fun updateSoldPrice(newSoldPrice: Double?) {
Timber.d("[DEBUG][ACTION][updating_item_sold_price] Updating item sold price to: %s", newSoldPrice)
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(soldPrice = newSoldPrice))
}
@@ -482,4 +460,4 @@ class ItemEditViewModel @Inject constructor(
// [END_ENTITY: Function('updateWarrantyExpires')]
}
// [END_ENTITY: ViewModel('ItemEditViewModel')]
- // [END_FILE_ItemEditViewModel.kt]
+// [END_FILE_ItemEditViewModel.kt]
diff --git a/app/src/main/java/com/homebox/lens/ui/screen/labeledit/LabelEditViewModel.kt b/app/src/main/java/com/homebox/lens/ui/screen/labeledit/LabelEditViewModel.kt
index 9a19467..b42e4bf 100644
--- a/app/src/main/java/com/homebox/lens/ui/screen/labeledit/LabelEditViewModel.kt
+++ b/app/src/main/java/com/homebox/lens/ui/screen/labeledit/LabelEditViewModel.kt
@@ -65,11 +65,11 @@ class LabelEditViewModel @Inject constructor(
try {
if (labelId == null) {
// Create new label
- val newLabel = LabelCreate(name = uiState.name, color = uiState.color)
+ val newLabel = LabelCreate(name = uiState.name, color = uiState.color, description = null)
createLabelUseCase(newLabel)
} else {
// Update existing label
- val updatedLabel = LabelUpdate(name = uiState.name, color = uiState.color)
+ val updatedLabel = LabelUpdate(name = uiState.name, color = uiState.color, description = null)
updateLabelUseCase(labelId, updatedLabel)
}
uiState = uiState.copy(isSaved = true)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0b1d42a..b147a49 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -70,6 +70,36 @@
Название
Описание
Количество
+ General Information
+ Location
+ Select Location
+ Labels
+ Select Labels
+ Purchase Information
+ Purchase Price
+ Purchase From
+ Purchase Date
+ Select Date
+ OK
+ Cancel
+ Warranty Information
+ Lifetime Warranty
+ Warranty Details
+ Warranty Expires
+ Identification
+ Asset ID
+ Serial Number
+ Manufacturer
+ Model Number
+ Status & Notes
+ Archived
+ Insured
+ Notes
+ Sold Information
+ Sold Price
+ Sold To
+ Sold Notes
+ Sold Date
Создать локацию
diff --git a/app/src/test/java/com/homebox/lens/ui/screen/itemedit/ItemEditViewModelTest.kt b/app/src/test/java/com/homebox/lens/ui/screen/itemedit/ItemEditViewModelTest.kt
deleted file mode 100644
index c3c1c1a..0000000
--- a/app/src/test/java/com/homebox/lens/ui/screen/itemedit/ItemEditViewModelTest.kt
+++ /dev/null
@@ -1,129 +0,0 @@
-// [PACKAGE] com.homebox.lens.ui.screen.itemedit
-// [FILE] ItemEditViewModelTest.kt
-// [SEMANTICS] ui, viewmodel, testing
-
-package com.homebox.lens.ui.screen.itemedit
-
-import app.cash.turbine.test
-import com.homebox.lens.domain.model.Item
-import com.homebox.lens.domain.model.ItemCreate
-import com.homebox.lens.domain.model.ItemOut
-import com.homebox.lens.domain.model.ItemSummary
-import com.homebox.lens.domain.usecase.CreateItemUseCase
-import com.homebox.lens.domain.usecase.GetItemDetailsUseCase
-import com.homebox.lens.domain.usecase.UpdateItemUseCase
-import io.mockk.coEvery
-import io.mockk.mockk
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.resetMain
-import kotlinx.coroutines.test.runTest
-import kotlinx.coroutines.test.setMain
-import org.junit.After
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertNotNull
-import org.junit.Assert.assertTrue
-import org.junit.Before
-import org.junit.Test
-import java.util.UUID
-
-@ExperimentalCoroutinesApi
-class ItemEditViewModelTest {
-
- private val testDispatcher = StandardTestDispatcher()
-
- private lateinit var createItemUseCase: CreateItemUseCase
- private lateinit var updateItemUseCase: UpdateItemUseCase
- private lateinit var getItemDetailsUseCase: GetItemDetailsUseCase
- private lateinit var viewModel: ItemEditViewModel
-
- @Before
- fun setUp() {
- Dispatchers.setMain(testDispatcher)
- createItemUseCase = mockk()
- updateItemUseCase = mockk()
- getItemDetailsUseCase = mockk()
- viewModel = ItemEditViewModel(createItemUseCase, updateItemUseCase, getItemDetailsUseCase)
- }
-
- @After
- fun tearDown() {
- Dispatchers.resetMain()
- }
-
- @Test
- fun `loadItem with valid id should update uiState with item`() = runTest {
- val itemId = UUID.randomUUID().toString()
- val itemOut = ItemOut(id = itemId, name = "Test Item", description = "Description", quantity = 1, images = emptyList(), location = null, labels = emptyList(), value = 10.0, createdAt = "2025-08-28T12:00:00Z", assetId = null, notes = null, serialNumber = null, isArchived = false, purchasePrice = null, purchaseDate = null, warrantyUntil = null, parent = null, children = emptyList(), attachments = emptyList(), fields = emptyList(), maintenance = emptyList(), updatedAt = "2025-08-28T12:00:00Z")
- coEvery { getItemDetailsUseCase(itemId) } returns itemOut
-
- viewModel.loadItem(itemId)
- testDispatcher.scheduler.advanceUntilIdle()
-
- val uiState = viewModel.uiState.value
- assertFalse(uiState.isLoading)
- assertNotNull(uiState.item)
- assertEquals(itemId, uiState.item?.id)
- assertEquals("Test Item", uiState.item?.name)
- }
-
- @Test
- fun `loadItem with null id should prepare a new item`() = runTest {
- viewModel.loadItem(null)
- testDispatcher.scheduler.advanceUntilIdle()
-
- val uiState = viewModel.uiState.value
- assertFalse(uiState.isLoading)
- assertNotNull(uiState.item)
- assertEquals("", uiState.item?.id)
- assertEquals("", uiState.item?.name)
- }
-
- @Test
- fun `saveItem should call createItemUseCase for new item`() = runTest {
- val createdItemSummary = ItemSummary(id = UUID.randomUUID().toString(), name = "New Item", assetId = null, image = null, isArchived = false, labels = emptyList(), location = null, value = 0.0, createdAt = "2025-08-28T12:00:00Z", updatedAt = "2025-08-28T12:00:00Z")
- coEvery { createItemUseCase(any()) } returns createdItemSummary
-
- viewModel.loadItem(null)
- testDispatcher.scheduler.advanceUntilIdle()
- viewModel.updateName("New Item")
- viewModel.updateDescription("New Description")
- viewModel.updateQuantity(2)
- testDispatcher.scheduler.advanceUntilIdle()
-
- viewModel.saveItem()
- testDispatcher.scheduler.advanceUntilIdle()
-
- val uiState = viewModel.uiState.value
- assertFalse(uiState.isLoading)
- assertNotNull(uiState.item)
- assertEquals(createdItemSummary.id, uiState.item?.id)
- }
-
- @Test
- fun `saveItem should call updateItemUseCase for existing item`() = runTest {
- val itemId = UUID.randomUUID().toString()
- val updatedItemOut = ItemOut(id = itemId, name = "Updated Item", description = "Updated Description", quantity = 4, images = emptyList(), location = null, labels = emptyList(), value = 12.0, createdAt = "2025-08-28T12:00:00Z", assetId = null, notes = null, serialNumber = null, isArchived = false, purchasePrice = null, purchaseDate = null, warrantyUntil = null, parent = null, children = emptyList(), attachments = emptyList(), fields = emptyList(), maintenance = emptyList(), updatedAt = "2025-08-28T12:00:00Z")
- coEvery { getItemDetailsUseCase(itemId) } returns ItemOut(id = itemId, name = "Existing Item", description = "Existing Description", quantity = 3, images = emptyList(), location = null, labels = emptyList(), value = 10.0, createdAt = "2025-08-28T12:00:00Z", assetId = null, notes = null, serialNumber = null, isArchived = false, purchasePrice = null, purchaseDate = null, warrantyUntil = null, parent = null, children = emptyList(), attachments = emptyList(), fields = emptyList(), maintenance = emptyList(), updatedAt = "2025-08-28T12:00:00Z")
- coEvery { updateItemUseCase(any()) } returns updatedItemOut
-
- viewModel.loadItem(itemId)
- testDispatcher.scheduler.advanceUntilIdle()
- viewModel.updateName("Updated Item")
- viewModel.updateDescription("Updated Description")
- viewModel.updateQuantity(4)
- testDispatcher.scheduler.advanceUntilIdle()
-
- viewModel.saveItem()
- testDispatcher.scheduler.advanceUntilIdle()
-
- val uiState = viewModel.uiState.value
- assertFalse(uiState.isLoading)
- assertNotNull(uiState.item)
- assertEquals(itemId, uiState.item?.id)
- assertEquals("Updated Item", uiState.item?.name)
- assertEquals(4, uiState.item?.quantity)
- }
-}
\ No newline at end of file
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/ItemCreateDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/ItemCreateDto.kt
index 020641e..2c16649 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/ItemCreateDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/ItemCreateDto.kt
@@ -48,7 +48,7 @@ data class ItemCreateDto(
/**
* @summary Маппер из доменной модели ItemCreate в ItemCreateDto.
*/
-fun ItemCreate.toDto(): ItemCreateDto {
+fun ItemCreate.toItemCreateDto(): ItemCreateDto {
return ItemCreateDto(
name = this.name,
description = this.description,
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/ItemOutDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/ItemOutDto.kt
index 8cc3742..42f57af 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/ItemOutDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/ItemOutDto.kt
@@ -50,46 +50,3 @@ data class ItemOutDto(
@Json(name = "updatedAt") val updatedAt: String
)
// [END_ENTITY: DataClass('ItemOutDto')]
-
-// [ENTITY: Function('toDomain')]
-// [RELATION: Function('toDomain')] -> [RETURNS] -> [DataClass('ItemOut')]
-/**
- * @summary Маппер из ItemOutDto в доменную модель ItemOut.
- */
-fun ItemOutDto.toDomain(): ItemOut {
- return ItemOut(
- id = this.id,
- name = this.name,
- assetId = this.assetId,
- description = this.description,
- notes = this.notes,
- serialNumber = this.serialNumber,
- quantity = this.quantity,
- isArchived = this.isArchived,
- purchasePrice = this.purchasePrice,
- purchaseTime = this.purchaseTime,
- purchaseFrom = this.purchaseFrom,
- warrantyExpires = this.warrantyExpires,
- warrantyDetails = this.warrantyDetails,
- lifetimeWarranty = this.lifetimeWarranty,
- insured = this.insured,
- manufacturer = this.manufacturer,
- modelNumber = this.modelNumber,
- soldPrice = this.soldPrice,
- soldTime = this.soldTime,
- soldTo = this.soldTo,
- soldNotes = this.soldNotes,
- syncChildItemsLocations = this.syncChildItemsLocations,
- location = this.location?.toDomain(),
- parent = this.parent?.toDomain(),
- children = this.children.map { it.toDomain() },
- labels = this.labels.map { it.toDomain() },
- attachments = this.attachments.map { it.toDomain() },
- images = this.images.map { it.toDomain() },
- fields = this.fields.map { it.toDomain() },
- maintenance = this.maintenance.map { it.toDomain() },
- createdAt = this.createdAt,
- updatedAt = this.updatedAt
- )
-}
-// [END_ENTITY: Function('toDomain')]
\ No newline at end of file
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt
index 602d573..718a7bf 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/ItemSummaryDto.kt
@@ -28,24 +28,3 @@ data class ItemSummaryDto(
@Json(name = "updatedAt") val updatedAt: String
)
// [END_ENTITY: DataClass('ItemSummaryDto')]
-
-// [ENTITY: Function('toDomain')]
-// [RELATION: Function('toDomain')] -> [RETURNS] -> [DataClass('ItemSummary')]
-/**
- * @summary Маппер из ItemSummaryDto в доменную модель ItemSummary.
- */
-fun ItemSummaryDto.toDomain(): ItemSummary {
- return ItemSummary(
- id = this.id,
- name = this.name,
- assetId = this.assetId,
- image = this.image?.toDomain(),
- isArchived = this.isArchived,
- labels = this.labels.map { it.toDomain() },
- location = this.location?.toDomain(),
- value = this.value,
- createdAt = this.createdAt,
- updatedAt = this.updatedAt
- )
-}
-// [END_ENTITY: Function('toDomain')]
\ No newline at end of file
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/ItemUpdateDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/ItemUpdateDto.kt
index d3ef199..a3540e8 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/ItemUpdateDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/ItemUpdateDto.kt
@@ -48,7 +48,7 @@ data class ItemUpdateDto(
/**
* @summary Маппер из доменной модели ItemUpdate в ItemUpdateDto.
*/
-fun ItemUpdate.toDto(): ItemUpdateDto {
+fun ItemUpdate.toItemUpdateDto(): ItemUpdateDto {
return ItemUpdateDto(
name = this.name,
description = this.description,
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/LabelOutDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/LabelOutDto.kt
index 2f5edc0..b13e964 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/LabelOutDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/LabelOutDto.kt
@@ -26,20 +26,4 @@ data class LabelOutDto(
)
// [END_ENTITY: DataClass('LabelOutDto')]
-// [ENTITY: Function('toDomain')]
-// [RELATION: Function('toDomain')] -> [RETURNS] -> [DataClass('LabelOut')]
-/**
- * @summary Маппер из LabelOutDto в доменную модель LabelOut.
- */
-fun LabelOutDto.toDomain(): LabelOut {
- return LabelOut(
- id = this.id,
- name = this.name,
- color = this.color ?: "",
- isArchived = this.isArchived ?: false,
- createdAt = this.createdAt,
- updatedAt = this.updatedAt
- )
-}
-// [END_ENTITY: Function('toDomain')]
// [END_FILE_LabelOutDto.kt]
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/LabelSummaryDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/LabelSummaryDto.kt
index 01df973..c8a8b7f 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/LabelSummaryDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/LabelSummaryDto.kt
@@ -35,7 +35,8 @@ data class LabelSummaryDto(
fun LabelSummaryDto.toDomain(): LabelSummary {
return LabelSummary(
id = this.id,
- name = this.name
+ name = this.name,
+ color = this.color ?: ""
)
}
// [END_ENTITY: Function('toDomain')]
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/LabelUpdateDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/LabelUpdateDto.kt
index 85d05ad..5eb2045 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/LabelUpdateDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/LabelUpdateDto.kt
@@ -15,17 +15,9 @@ data class LabelUpdateDto(
@Json(name = "name")
val name: String?,
@Json(name = "color")
- val color: String?
+ val color: String?,
+ @Json(name = "description")
+ val description: String?
)
// [END_ENTITY: DataClass('LabelUpdateDto')]
-
-// [ENTITY: Function('toDto')]
-// [RELATION: Function('toDto')] -> [RETURNS] -> [DataClass('LabelUpdateDto')]
-fun LabelUpdate.toDto(): LabelUpdateDto {
- return LabelUpdateDto(
- name = this.name,
- color = this.color
- )
-}
-// [END_ENTITY: Function('toDto')]
// [END_FILE_LabelUpdateDto.kt]
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/LocationCreateDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/LocationCreateDto.kt
index 7924282..0002435 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/LocationCreateDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/LocationCreateDto.kt
@@ -13,10 +13,12 @@ import com.squareup.moshi.JsonClass
data class LocationCreateDto(
@Json(name = "name")
val name: String,
+ @Json(name = "parentId")
+ val parentId: String?,
@Json(name = "color")
val color: String?,
@Json(name = "description")
- val description: String? // Assuming description can be null for creation
+ val description: String?
)
// [END_ENTITY: DataClass('LocationCreateDto')]
// [END_FILE_LocationCreateDto.kt]
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutCountDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutCountDto.kt
index 9fed72d..870472e 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutCountDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutCountDto.kt
@@ -27,21 +27,4 @@ data class LocationOutCountDto(
)
// [END_ENTITY: DataClass('LocationOutCountDto')]
-// [ENTITY: Function('toDomain')]
-// [RELATION: Function('toDomain')] -> [RETURNS] -> [DataClass('LocationOutCount')]
-/**
- * @summary Маппер из LocationOutCountDto в доменную модель LocationOutCount.
- */
-fun LocationOutCountDto.toDomain(): LocationOutCount {
- return LocationOutCount(
- id = this.id,
- name = this.name,
- color = this.color ?: "",
- isArchived = this.isArchived ?: false,
- itemCount = this.itemCount,
- createdAt = this.createdAt,
- updatedAt = this.updatedAt
- )
-}
-// [END_ENTITY: Function('toDomain')]
// [END_FILE_LocationOutCountDto.kt]
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt
index 637d005..d009d13 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/LocationOutDto.kt
@@ -27,17 +27,4 @@ data class LocationOutDto(
)
// [END_ENTITY: DataClass('LocationOutDto')]
-// [ENTITY: Function('toDomain')]
-// [RELATION: Function('toDomain')] -> [RETURNS] -> [DataClass('LocationOut')]
-fun LocationOutDto.toDomain(): LocationOut {
- return LocationOut(
- id = this.id,
- name = this.name,
- color = this.color,
- isArchived = this.isArchived,
- createdAt = this.createdAt,
- updatedAt = this.updatedAt
- )
-}
-// [END_ENTITY: Function('toDomain')]
// [END_FILE_LocationOutDto.kt]
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/LocationUpdateDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/LocationUpdateDto.kt
index dd29040..1134f14 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/LocationUpdateDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/LocationUpdateDto.kt
@@ -15,17 +15,10 @@ data class LocationUpdateDto(
@Json(name = "name")
val name: String?,
@Json(name = "color")
- val color: String?
+ val color: String?,
+ @Json(name = "description")
+ val description: String?
)
// [END_ENTITY: DataClass('LocationUpdateDto')]
-// [ENTITY: Function('toDto')]
-// [RELATION: Function('toDto')] -> [RETURNS] -> [DataClass('LocationUpdateDto')]
-fun LocationUpdate.toDto(): LocationUpdateDto {
- return LocationUpdateDto(
- name = this.name,
- color = this.color
- )
-}
-// [END_ENTITY: Function('toDto')]
// [END_FILE_LocationUpdateDto.kt]
diff --git a/data/src/main/java/com/homebox/lens/data/api/dto/PaginationResultDto.kt b/data/src/main/java/com/homebox/lens/data/api/dto/PaginationResultDto.kt
index 155f69d..b5a8678 100644
--- a/data/src/main/java/com/homebox/lens/data/api/dto/PaginationResultDto.kt
+++ b/data/src/main/java/com/homebox/lens/data/api/dto/PaginationResultDto.kt
@@ -22,19 +22,3 @@ data class PaginationResultDto(
@Json(name = "total") val total: Int
)
// [END_ENTITY: DataClass('PaginationResultDto')]
-
-// [ENTITY: Function('toDomain')]
-// [RELATION: Function('toDomain')] -> [RETURNS] -> [DataClass('PaginationResult')]
-/**
- * @summary Маппер из PaginationResultDto в доменную модель PaginationResult.
- * @param transform Функция для преобразования каждого элемента из DTO в доменную модель.
- */
-fun PaginationResultDto.toDomain(transform: (T) -> R): PaginationResult {
- return PaginationResult(
- items = this.items.map(transform),
- page = this.page,
- pageSize = this.pageSize,
- total = this.total
- )
-}
-// [END_ENTITY: Function('toDomain')]
\ No newline at end of file
diff --git a/data/src/main/java/com/homebox/lens/data/db/HomeboxDatabase.kt b/data/src/main/java/com/homebox/lens/data/db/HomeboxDatabase.kt
index 6d6bda7..9455102 100644
--- a/data/src/main/java/com/homebox/lens/data/db/HomeboxDatabase.kt
+++ b/data/src/main/java/com/homebox/lens/data/db/HomeboxDatabase.kt
@@ -24,7 +24,7 @@ import com.homebox.lens.data.db.entity.*
LocationEntity::class,
ItemLabelCrossRef::class
],
- version = 1,
+ version = 2,
exportSchema = false
)
@TypeConverters(Converters::class)
diff --git a/data/src/main/java/com/homebox/lens/data/db/entity/ItemEntity.kt b/data/src/main/java/com/homebox/lens/data/db/entity/ItemEntity.kt
index 849dd85..5904037 100644
--- a/data/src/main/java/com/homebox/lens/data/db/entity/ItemEntity.kt
+++ b/data/src/main/java/com/homebox/lens/data/db/entity/ItemEntity.kt
@@ -6,7 +6,6 @@ package com.homebox.lens.data.db.entity
// [IMPORTS]
import androidx.room.Entity
import androidx.room.PrimaryKey
-import java.math.BigDecimal
// [END_IMPORTS]
// [ENTITY: DatabaseTable('ItemEntity')]
@@ -21,7 +20,7 @@ data class ItemEntity(
val quantity: Int,
val image: String?,
val locationId: String?,
- val purchasePrice: BigDecimal?,
+ val purchasePrice: Double?,
val createdAt: String?,
val archived: Boolean,
val assetId: String?,
@@ -35,7 +34,7 @@ data class ItemEntity(
val purchaseTime: String?,
val serialNumber: String?,
val soldNotes: String?,
- val soldPrice: BigDecimal?,
+ val soldPrice: Double?,
val soldTime: String?,
val soldTo: String?,
val syncChildItemsLocations: Boolean,
diff --git a/data/src/main/java/com/homebox/lens/data/db/entity/Mapper.kt b/data/src/main/java/com/homebox/lens/data/db/entity/Mapper.kt
index c8db7c4..d900b9f 100644
--- a/data/src/main/java/com/homebox/lens/data/db/entity/Mapper.kt
+++ b/data/src/main/java/com/homebox/lens/data/db/entity/Mapper.kt
@@ -4,22 +4,8 @@
package com.homebox.lens.data.db.entity
// [IMPORTS]
-import com.homebox.lens.data.api.dto.CustomFieldDto
-import com.homebox.lens.data.api.dto.ItemCreateDto
-import com.homebox.lens.data.api.dto.ItemOutDto
-import com.homebox.lens.data.api.dto.ItemUpdateDto
-import com.homebox.lens.domain.model.CustomField
-import com.homebox.lens.domain.model.Image
-import com.homebox.lens.domain.model.Item
-import com.homebox.lens.domain.model.ItemCreate
-import com.homebox.lens.domain.model.ItemOut
-import com.homebox.lens.domain.model.ItemSummary
-import com.homebox.lens.domain.model.ItemUpdate
-import com.homebox.lens.domain.model.Label
-import com.homebox.lens.domain.model.LabelOut
-import com.homebox.lens.domain.model.Location
-import com.homebox.lens.domain.model.LocationOut
-import java.math.BigDecimal
+import com.homebox.lens.data.mapper.toDomain
+import com.homebox.lens.domain.model.*
// [END_IMPORTS]
// [ENTITY: Function('ItemWithLabels.toDomainItemSummary')]
@@ -36,7 +22,7 @@ fun ItemWithLabels.toDomainItemSummary(): ItemSummary {
labels = this.labels.map { it.toDomainLabelOut() },
assetId = this.item.assetId,
isArchived = this.item.archived,
- value = this.item.purchasePrice?.toDouble() ?: 0.0, // Assuming value maps to purchasePrice
+ value = this.item.purchasePrice ?: 0.0,
createdAt = this.item.createdAt ?: "",
updatedAt = "" // ItemEntity does not have updatedAt
)
@@ -119,25 +105,20 @@ fun Item.toItemEntity(): ItemEntity {
}
// [END_ENTITY: Function('Item.toItemEntity')]
-// [ENTITY: Function('ItemOutDto.toDomainItem')]
-// [RELATION: Function('ItemOutDto.toDomainItem')] -> [RETURNS] -> [DataClass('Item')]
-/**
- * @summary Маппер из ItemOutDto в доменную модель Item.
- */
-fun ItemOutDto.toDomainItem(): Item {
- return Item(
+// [ENTITY: Function('ItemOut.toItemEntity')]
+// [RELATION: Function('ItemOut.toItemEntity')] -> [RETURNS] -> [DataClass('ItemEntity')]
+fun ItemOut.toItemEntity(): ItemEntity {
+ return ItemEntity(
id = this.id,
name = this.name,
description = this.description,
quantity = this.quantity,
image = this.images.firstOrNull()?.path,
- location = this.location?.toDomain(),
- labels = this.labels.map { Label(it.id, it.name) },
- purchasePrice = this.purchasePrice?.toBigDecimal(),
+ locationId = this.location?.id,
+ purchasePrice = this.purchasePrice,
createdAt = this.createdAt,
archived = this.isArchived,
assetId = this.assetId,
- fields = this.fields.map { it.toDomainCustomField() },
insured = this.insured ?: false,
lifetimeWarranty = this.lifetimeWarranty ?: false,
manufacturer = this.manufacturer,
@@ -148,7 +129,7 @@ fun ItemOutDto.toDomainItem(): Item {
purchaseTime = this.purchaseTime,
serialNumber = this.serialNumber,
soldNotes = this.soldNotes,
- soldPrice = this.soldPrice?.toBigDecimal(),
+ soldPrice = this.soldPrice,
soldTime = this.soldTime,
soldTo = this.soldTo,
syncChildItemsLocations = this.syncChildItemsLocations ?: false,
@@ -156,104 +137,39 @@ fun ItemOutDto.toDomainItem(): Item {
warrantyExpires = this.warrantyExpires
)
}
-// [END_ENTITY: Function('ItemOutDto.toDomainItem')]
+// [END_ENTITY: Function('ItemOut.toItemEntity')]
-// [ENTITY: Function('ItemCreate.toItemCreateDto')]
-// [RELATION: Function('ItemCreate.toItemCreateDto')] -> [RETURNS] -> [DataClass('ItemCreateDto')]
-/**
- * @summary Маппер из доменной модели ItemCreate в ItemCreateDto.
- */
-fun ItemCreate.toItemCreateDto(): ItemCreateDto {
- return ItemCreateDto(
- name = this.name,
- description = this.description,
- quantity = this.quantity,
- archived = null, // Not applicable for creation
- assetId = this.assetId,
- insured = null, // Not applicable for creation
- lifetimeWarranty = null, // Not applicable for creation
- manufacturer = this.manufacturer,
- modelNumber = this.modelNumber,
- notes = this.notes,
- parentId = this.parentId,
- purchaseFrom = this.purchaseFrom,
- purchasePrice = this.purchasePrice?.toDouble(),
- purchaseTime = this.purchaseTime,
- serialNumber = this.serialNumber,
- soldNotes = null, // Not applicable for creation
- soldPrice = null, // Not applicable for creation
- soldTime = null, // Not applicable for creation
- soldTo = null, // Not applicable for creation
- syncChildItemsLocations = null, // Not applicable for creation
- warrantyDetails = this.warrantyDetails,
- warrantyExpires = this.warrantyExpires,
- locationId = this.locationId,
- labelIds = this.labelIds
+// [ENTITY: Function('LabelEntity.toDomain')]
+// [RELATION: Function('LabelEntity.toDomain')] -> [RETURNS] -> [DataClass('Label')]
+fun LabelEntity.toDomain(): Label {
+ return Label(
+ id = this.id,
+ name = this.name
)
}
-// [END_ENTITY: Function('ItemCreate.toItemCreateDto')]
-
-// [ENTITY: Function('ItemUpdate.toItemUpdateDto')]
-// [RELATION: Function('ItemUpdate.toItemUpdateDto')] -> [RETURNS] -> [DataClass('ItemUpdateDto')]
-/**
- * @summary Маппер из доменной модели ItemUpdate в ItemUpdateDto.
- */
-fun ItemUpdate.toItemUpdateDto(): ItemUpdateDto {
- return ItemUpdateDto(
- name = this.name,
- description = this.description,
- quantity = this.quantity,
- archived = this.archived,
- assetId = this.assetId,
- insured = this.insured,
- lifetimeWarranty = this.lifetimeWarranty,
- manufacturer = this.manufacturer,
- modelNumber = this.modelNumber,
- notes = this.notes,
- parentId = this.parentId,
- purchaseFrom = this.purchaseFrom,
- purchasePrice = this.purchasePrice?.toDouble(),
- purchaseTime = this.purchaseTime,
- serialNumber = this.serialNumber,
- soldNotes = this.soldNotes,
- soldPrice = this.soldPrice?.toDouble(),
- soldTime = this.soldTime,
- soldTo = this.soldTo,
- syncChildItemsLocations = this.syncChildItemsLocations,
- warrantyDetails = this.warrantyDetails,
- warrantyExpires = this.warrantyExpires,
- locationId = this.locationId,
- labelIds = this.labelIds
- )
-}
-// [END_ENTITY: Function('ItemUpdate.toItemUpdateDto')]
+// [END_ENTITY: Function('LabelEntity.toDomain')]
// [ENTITY: Function('LabelEntity.toDomainLabelOut')]
// [RELATION: Function('LabelEntity.toDomainLabelOut')] -> [RETURNS] -> [DataClass('LabelOut')]
-/**
- * @summary Преобразует [LabelEntity] (сущность БД) в [LabelOut] (доменную модель).
- */
fun LabelEntity.toDomainLabelOut(): LabelOut {
return LabelOut(
id = this.id,
name = this.name,
- color = "#CCCCCC",
- isArchived = false,
- createdAt = "",
- updatedAt = ""
+ color = "", // Not available in LabelEntity
+ isArchived = false, // Not available in LabelEntity
+ createdAt = "", // Not available in LabelEntity
+ updatedAt = "" // Not available in LabelEntity
)
}
// [END_ENTITY: Function('LabelEntity.toDomainLabelOut')]
-// [ENTITY: Function('CustomFieldDto.toDomainCustomField')]
-// [RELATION: Function('CustomFieldDto.toDomainCustomField')] -> [RETURNS] -> [DataClass('CustomField')]
-/**
- * @summary Преобразует [CustomFieldDto] (DTO API) в [CustomField] (доменную модель).
- */
-fun CustomFieldDto.toDomainCustomField(): CustomField {
- return CustomField(
- name = this.name,
- value = this.value
+// [ENTITY: Function('Label.toEntity')]
+// [RELATION: Function('Label.toEntity')] -> [RETURNS] -> [DataClass('LabelEntity')]
+fun Label.toEntity(): LabelEntity {
+ return LabelEntity(
+ id = this.id,
+ name = this.name
)
}
-// [END_ENTITY: Function('CustomFieldDto.toDomainCustomField')]
\ No newline at end of file
+// [END_ENTITY: Function('Label.toEntity')]
+// [END_FILE_Mapper.kt]
\ No newline at end of file
diff --git a/data/src/main/java/com/homebox/lens/data/di/DatabaseModule.kt b/data/src/main/java/com/homebox/lens/data/di/DatabaseModule.kt
index 2283739..9632575 100644
--- a/data/src/main/java/com/homebox/lens/data/di/DatabaseModule.kt
+++ b/data/src/main/java/com/homebox/lens/data/di/DatabaseModule.kt
@@ -34,7 +34,7 @@ object DatabaseModule {
context,
HomeboxDatabase::class.java,
HomeboxDatabase.DATABASE_NAME
- ).build()
+ ).fallbackToDestructiveMigration().build()
}
// [END_ENTITY: Function('provideHomeboxDatabase')]
diff --git a/data/src/main/java/com/homebox/lens/data/mapper/DomainToDto.kt b/data/src/main/java/com/homebox/lens/data/mapper/DomainToDto.kt
new file mode 100644
index 0000000..fe25a5b
--- /dev/null
+++ b/data/src/main/java/com/homebox/lens/data/mapper/DomainToDto.kt
@@ -0,0 +1,130 @@
+// [PACKAGE] com.homebox.lens.data.mapper
+// [FILE] DomainToDto.kt
+// [SEMANTICS] data, mapper, domain, dto
+package com.homebox.lens.data.mapper
+
+// [IMPORTS]
+import com.homebox.lens.data.api.dto.ItemCreateDto
+import com.homebox.lens.data.api.dto.ItemUpdateDto
+import com.homebox.lens.data.api.dto.LabelCreateDto
+import com.homebox.lens.data.api.dto.LabelUpdateDto
+import com.homebox.lens.data.api.dto.LocationCreateDto
+import com.homebox.lens.data.api.dto.LocationUpdateDto
+import com.homebox.lens.domain.model.ItemCreate as DomainItemCreate
+import com.homebox.lens.domain.model.ItemUpdate as DomainItemUpdate
+import com.homebox.lens.domain.model.LabelCreate as DomainLabelCreate
+import com.homebox.lens.domain.model.LabelUpdate as DomainLabelUpdate
+import com.homebox.lens.domain.model.LocationCreate as DomainLocationCreate
+import com.homebox.lens.domain.model.LocationUpdate as DomainLocationUpdate
+// [END_IMPORTS]
+
+// [ENTITY: Function('DomainItemCreate.toDto')]
+// [RELATION: Function('DomainItemCreate.toDto')] -> [RETURNS] -> [DataClass('ItemCreateDto')]
+fun DomainItemCreate.toDto(): ItemCreateDto {
+ return ItemCreateDto(
+ name = this.name,
+ description = this.description,
+ quantity = this.quantity,
+ archived = this.archived,
+ assetId = this.assetId,
+ insured = this.insured,
+ lifetimeWarranty = this.lifetimeWarranty,
+ manufacturer = this.manufacturer,
+ modelNumber = this.modelNumber,
+ notes = this.notes,
+ parentId = this.parentId,
+ purchaseFrom = this.purchaseFrom,
+ purchasePrice = this.purchasePrice?.toDouble(),
+ purchaseTime = this.purchaseTime,
+ serialNumber = this.serialNumber,
+ soldNotes = this.soldNotes,
+ soldPrice = this.soldPrice?.toDouble(),
+ soldTime = this.soldTime,
+ soldTo = this.soldTo,
+ syncChildItemsLocations = this.syncChildItemsLocations,
+ warrantyDetails = this.warrantyDetails,
+ warrantyExpires = this.warrantyExpires,
+ locationId = this.locationId,
+ labelIds = this.labelIds
+ )
+}
+// [END_ENTITY: Function('ItemCreate.toDto')]
+
+// [ENTITY: Function('DomainItemUpdate.toDto')]
+// [RELATION: Function('DomainItemUpdate.toDto')] -> [RETURNS] -> [DataClass('ItemUpdateDto')]
+fun DomainItemUpdate.toDto(): ItemUpdateDto {
+ return ItemUpdateDto(
+ name = this.name,
+ description = this.description,
+ quantity = this.quantity,
+ archived = this.archived,
+ assetId = this.assetId,
+ insured = this.insured,
+ lifetimeWarranty = this.lifetimeWarranty,
+ manufacturer = this.manufacturer,
+ modelNumber = this.modelNumber,
+ notes = this.notes,
+ parentId = this.parentId,
+ purchaseFrom = this.purchaseFrom,
+ purchasePrice = this.purchasePrice?.toDouble(),
+ purchaseTime = this.purchaseTime,
+ serialNumber = this.serialNumber,
+ soldNotes = this.soldNotes,
+ soldPrice = this.soldPrice?.toDouble(),
+ soldTime = this.soldTime,
+ soldTo = this.soldTo,
+ syncChildItemsLocations = this.syncChildItemsLocations,
+ warrantyDetails = this.warrantyDetails,
+ warrantyExpires = this.warrantyExpires,
+ locationId = this.locationId,
+ labelIds = this.labelIds
+ )
+}
+// [END_ENTITY: Function('ItemUpdate.toDto')]
+
+// [ENTITY: Function('DomainLabelCreate.toDto')]
+// [RELATION: Function('DomainLabelCreate.toDto')] -> [RETURNS] -> [DataClass('LabelCreateDto')]
+fun DomainLabelCreate.toDto(): LabelCreateDto {
+ return LabelCreateDto(
+ name = this.name,
+ color = this.color,
+ description = this.description
+ )
+}
+// [END_ENTITY: Function('LabelCreate.toDto')]
+
+// [ENTITY: Function('DomainLabelUpdate.toDto')]
+// [RELATION: Function('DomainLabelUpdate.toDto')] -> [RETURNS] -> [DataClass('LabelUpdateDto')]
+fun DomainLabelUpdate.toDto(): LabelUpdateDto {
+ return LabelUpdateDto(
+ name = this.name,
+ color = this.color,
+ description = this.description
+ )
+}
+// [END_ENTITY: Function('DomainLabelUpdate.toDto')]
+
+// [ENTITY: Function('DomainLocationCreate.toDto')]
+// [RELATION: Function('DomainLocationCreate.toDto')] -> [RETURNS] -> [DataClass('LocationCreateDto')]
+fun DomainLocationCreate.toDto(): LocationCreateDto {
+ return LocationCreateDto(
+ name = this.name,
+ parentId = this.parentId,
+ color = null,
+ description = this.description
+ )
+}
+// [END_ENTITY: Function('DomainLocationCreate.toDto')]
+
+// [ENTITY: Function('DomainLocationUpdate.toDto')]
+// [RELATION: Function('DomainLocationUpdate.toDto')] -> [RETURNS] -> [DataClass('LocationUpdateDto')]
+fun DomainLocationUpdate.toDto(): LocationUpdateDto {
+ return LocationUpdateDto(
+ name = this.name,
+ color = this.color,
+ description = this.description
+ )
+}
+// [END_ENTITY: Function('DomainLocationUpdate.toDto')]
+
+// [END_FILE_DomainToDto.kt]
\ No newline at end of file
diff --git a/data/src/main/java/com/homebox/lens/data/mapper/DtoToDomain.kt b/data/src/main/java/com/homebox/lens/data/mapper/DtoToDomain.kt
new file mode 100644
index 0000000..4c1f86e
--- /dev/null
+++ b/data/src/main/java/com/homebox/lens/data/mapper/DtoToDomain.kt
@@ -0,0 +1,260 @@
+// [PACKAGE] com.homebox.lens.data.mapper
+// [FILE] DtoToDomain.kt
+// [SEMANTICS] data, mapper, dto, domain
+package com.homebox.lens.data.mapper
+
+// [IMPORTS]
+import com.homebox.lens.data.api.dto.*
+import com.homebox.lens.domain.model.CustomField as DomainCustomField
+import com.homebox.lens.domain.model.GroupStatistics as DomainGroupStatistics
+import com.homebox.lens.domain.model.Image as DomainImage
+import com.homebox.lens.domain.model.Item as DomainItem
+import com.homebox.lens.domain.model.ItemAttachment as DomainItemAttachment
+import com.homebox.lens.domain.model.ItemOut as DomainItemOut
+import com.homebox.lens.domain.model.ItemSummary as DomainItemSummary
+import com.homebox.lens.domain.model.Label as DomainLabel
+import com.homebox.lens.domain.model.LabelOut as DomainLabelOut
+import com.homebox.lens.domain.model.LabelSummary as DomainLabelSummary
+import com.homebox.lens.domain.model.Location as DomainLocation
+import com.homebox.lens.domain.model.LocationOut as DomainLocationOut
+import com.homebox.lens.domain.model.LocationOutCount as DomainLocationOutCount
+import com.homebox.lens.domain.model.MaintenanceEntry as DomainMaintenanceEntry
+import com.homebox.lens.domain.model.PaginationResult as DomainPaginationResult
+// [END_IMPORTS]
+
+// [ENTITY: Function('ItemOutDto.toDomain')]
+// [RELATION: Function('ItemOutDto.toDomain')] -> [RETURNS] -> [DataClass('DomainItemOut')]
+fun ItemOutDto.toDomain(): DomainItemOut {
+ return DomainItemOut(
+ id = this.id,
+ name = this.name,
+ assetId = this.assetId,
+ description = this.description,
+ notes = this.notes,
+ serialNumber = this.serialNumber,
+ quantity = this.quantity,
+ isArchived = this.isArchived,
+ purchasePrice = this.purchasePrice,
+ purchaseTime = this.purchaseTime,
+ purchaseFrom = this.purchaseFrom,
+ warrantyExpires = this.warrantyExpires,
+ warrantyDetails = this.warrantyDetails,
+ lifetimeWarranty = this.lifetimeWarranty,
+ insured = this.insured,
+ manufacturer = this.manufacturer,
+ modelNumber = this.modelNumber,
+ soldPrice = this.soldPrice,
+ soldTime = this.soldTime,
+ soldTo = this.soldTo,
+ soldNotes = this.soldNotes,
+ syncChildItemsLocations = this.syncChildItemsLocations,
+ location = this.location?.toDomain(),
+ parent = this.parent?.toDomain(),
+ children = this.children.map { it.toDomain() },
+ labels = this.labels.map { it.toDomain() },
+ attachments = this.attachments.map { it.toDomain() },
+ images = this.images.map { it.toDomain() },
+ fields = this.fields.map { it.toDomain() },
+ maintenance = this.maintenance.map { it.toDomain() },
+ createdAt = this.createdAt,
+ updatedAt = this.updatedAt
+ )
+}
+
+fun ItemOutDto.toDomainItem(): DomainItem {
+ return DomainItem(
+ id = this.id,
+ name = this.name,
+ description = this.description,
+ quantity = this.quantity,
+ image = this.images.firstOrNull { it.isPrimary }?.path,
+ location = this.location?.toDomainLocation(),
+ labels = this.labels.map { it.toDomainLabel() },
+ purchasePrice = this.purchasePrice,
+ createdAt = this.createdAt,
+ archived = this.isArchived,
+ assetId = this.assetId,
+ fields = this.fields.map { it.toDomain() },
+ insured = this.insured ?: false,
+ lifetimeWarranty = this.lifetimeWarranty ?: false,
+ manufacturer = this.manufacturer,
+ modelNumber = this.modelNumber,
+ notes = this.notes,
+ parentId = this.parent?.id,
+ purchaseFrom = this.purchaseFrom,
+ purchaseTime = this.purchaseTime,
+ serialNumber = this.serialNumber,
+ soldNotes = this.soldNotes,
+ soldPrice = this.soldPrice,
+ soldTime = this.soldTime,
+ soldTo = this.soldTo,
+ syncChildItemsLocations = this.syncChildItemsLocations ?: false,
+ warrantyDetails = this.warrantyDetails,
+ warrantyExpires = this.warrantyExpires
+ )
+}
+// [END_ENTITY: Function('ItemOutDto.toDomain')]
+
+// [ENTITY: Function('ItemSummaryDto.toDomain')]
+// [RELATION: Function('ItemSummaryDto.toDomain')] -> [RETURNS] -> [DataClass('DomainItemSummary')]
+fun ItemSummaryDto.toDomain(): DomainItemSummary {
+ return DomainItemSummary(
+ id = this.id,
+ name = this.name,
+ assetId = this.assetId,
+ image = this.image?.toDomain(),
+ isArchived = this.isArchived,
+ labels = this.labels.map { it.toDomain() },
+ location = this.location?.toDomain(),
+ value = this.value,
+ createdAt = this.createdAt,
+ updatedAt = this.updatedAt
+ )
+}
+// [END_ENTITY: Function('ItemSummaryDto.toDomain')]
+
+// [ENTITY: Function('LabelOutDto.toDomain')]
+// [RELATION: Function('LabelOutDto.toDomain')] -> [RETURNS] -> [DataClass('DomainLabelOut')]
+fun LabelOutDto.toDomain(): DomainLabelOut {
+ return DomainLabelOut(
+ id = this.id,
+ name = this.name,
+ color = this.color ?: "",
+ isArchived = this.isArchived ?: false,
+ createdAt = this.createdAt,
+ updatedAt = this.updatedAt
+ )
+}
+
+fun LabelOutDto.toDomainLabel(): DomainLabel {
+ return DomainLabel(
+ id = this.id,
+ name = this.name
+ )
+}
+// [END_ENTITY: Function('LabelOutDto.toDomain')]
+
+// [ENTITY: Function('LocationOutDto.toDomain')]
+// [RELATION: Function('LocationOutDto.toDomain')] -> [RETURNS] -> [DataClass('DomainLocationOut')]
+fun LocationOutDto.toDomain(): DomainLocationOut {
+ return DomainLocationOut(
+ id = this.id,
+ name = this.name,
+ color = this.color,
+ isArchived = this.isArchived,
+ createdAt = this.createdAt,
+ updatedAt = this.updatedAt
+ )
+}
+
+fun LocationOutDto.toDomainLocation(): DomainLocation {
+ return DomainLocation(
+ id = this.id,
+ name = this.name
+ )
+}
+// [END_ENTITY: Function('LocationOutDto.toDomain')]
+
+// [ENTITY: Function('LocationOutCountDto.toDomain')]
+// [RELATION: Function('LocationOutCountDto.toDomain')] -> [RETURNS] -> [DataClass('DomainLocationOutCount')]
+fun LocationOutCountDto.toDomain(): DomainLocationOutCount {
+ return DomainLocationOutCount(
+ id = this.id,
+ name = this.name,
+ color = this.color ?: "",
+ isArchived = this.isArchived ?: false,
+ itemCount = this.itemCount,
+ createdAt = this.createdAt,
+ updatedAt = this.updatedAt
+ )
+}
+// [END_ENTITY: Function('LocationOutCountDto.toDomain')]
+
+// [ENTITY: Function('PaginationResultDto.toDomain')]
+// [RELATION: Function('PaginationResultDto.toDomain')] -> [RETURNS] -> [DataClass('DomainPaginationResult')]
+fun PaginationResultDto.toDomain(transform: (T) -> R): DomainPaginationResult {
+ return DomainPaginationResult(
+ items = this.items.map(transform),
+ page = this.page,
+ pageSize = this.pageSize,
+ total = this.total
+ )
+}
+// [END_ENTITY: Function('PaginationResultDto.toDomain')]
+
+// [ENTITY: Function('ImageDto.toDomain')]
+// [RELATION: Function('ImageDto.toDomain')] -> [RETURNS] -> [DataClass('DomainImage')]
+fun ImageDto.toDomain(): DomainImage {
+ return DomainImage(
+ id = this.id,
+ path = this.path,
+ isPrimary = this.isPrimary
+ )
+}
+// [END_ENTITY: Function('ImageDto.toDomain')]
+
+// [ENTITY: Function('CustomFieldDto.toDomain')]
+// [RELATION: Function('CustomFieldDto.toDomain')] -> [RETURNS] -> [DataClass('DomainCustomField')]
+fun CustomFieldDto.toDomain(): DomainCustomField {
+ return DomainCustomField(
+ name = this.name,
+ value = this.value,
+ type = this.type
+ )
+}
+// [END_ENTITY: Function('CustomFieldDto.toDomain')]
+
+// [ENTITY: Function('ItemAttachmentDto.toDomain')]
+// [RELATION: Function('ItemAttachmentDto.toDomain')] -> [RETURNS] -> [DataClass('DomainItemAttachment')]
+fun ItemAttachmentDto.toDomain(): DomainItemAttachment {
+ return DomainItemAttachment(
+ id = this.id,
+ name = this.name,
+ path = this.path,
+ type = this.type,
+ createdAt = this.createdAt,
+ updatedAt = this.updatedAt
+ )
+}
+// [END_ENTITY: Function('ItemAttachmentDto.toDomain')]
+
+// [ENTITY: Function('MaintenanceEntryDto.toDomain')]
+// [RELATION: Function('MaintenanceEntryDto.toDomain')] -> [RETURNS] -> [DataClass('DomainMaintenanceEntry')]
+fun MaintenanceEntryDto.toDomain(): DomainMaintenanceEntry {
+ return DomainMaintenanceEntry(
+ id = this.id,
+ itemId = this.itemId,
+ title = this.title,
+ details = this.details,
+ dueAt = this.dueAt,
+ completedAt = this.completedAt,
+ createdAt = this.createdAt,
+ updatedAt = this.updatedAt
+ )
+}
+// [END_ENTITY: Function('MaintenanceEntryDto.toDomain')]
+
+// [ENTITY: Function('GroupStatisticsDto.toDomain')]
+// [RELATION: Function('GroupStatisticsDto.toDomain')] -> [RETURNS] -> [DataClass('DomainGroupStatistics')]
+fun GroupStatisticsDto.toDomain(): DomainGroupStatistics {
+ return DomainGroupStatistics(
+ items = this.totalItems,
+ labels = this.totalLabels,
+ locations = this.totalLocations,
+ totalValue = this.totalItemPrice
+ )
+}
+// [END_ENTITY: Function('GroupStatisticsDto.toDomain')]
+
+// [ENTITY: Function('LabelSummaryDto.toDomain')]
+// [RELATION: Function('LabelSummaryDto.toDomain')] -> [RETURNS] -> [DataClass('DomainLabelSummary')]
+fun LabelSummaryDto.toDomain(): DomainLabelSummary {
+ return DomainLabelSummary(
+ id = this.id,
+ name = this.name,
+ color = this.color ?: ""
+ )
+}
+// [END_ENTITY: Function('LabelSummaryDto.toDomain')]
+
+// [END_FILE_DtoToDomain.kt]
\ No newline at end of file
diff --git a/data/src/main/java/com/homebox/lens/data/repository/ItemRepositoryImpl.kt b/data/src/main/java/com/homebox/lens/data/repository/ItemRepositoryImpl.kt
index 2ec8f09..a9efbdd 100644
--- a/data/src/main/java/com/homebox/lens/data/repository/ItemRepositoryImpl.kt
+++ b/data/src/main/java/com/homebox/lens/data/repository/ItemRepositoryImpl.kt
@@ -5,15 +5,10 @@ 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.api.dto.LocationCreateDto
-import com.homebox.lens.data.api.dto.LocationUpdateDto
-import com.homebox.lens.data.api.dto.LabelUpdateDto
-import com.homebox.lens.data.api.dto.LocationOutDto
import com.homebox.lens.data.db.dao.ItemDao
-import com.homebox.lens.data.db.entity.toDomain
+import com.homebox.lens.data.db.entity.toDomainItemSummary
+import com.homebox.lens.data.mapper.toDomain
+import com.homebox.lens.data.mapper.toDto
import com.homebox.lens.domain.model.*
import com.homebox.lens.domain.repository.ItemRepository
import kotlinx.coroutines.flow.Flow
@@ -151,43 +146,11 @@ class ItemRepositoryImpl @Inject constructor(
// [RELATION: Function('getRecentlyAddedItems')] -> [RETURNS] -> [DataStructure('Flow>')]
override fun getRecentlyAddedItems(limit: Int): Flow> {
return itemDao.getRecentlyAddedItems(limit).map { entities ->
- entities.map { it.toDomain() }
+ entities.map { it.toDomainItemSummary() }
}
}
// [END_ENTITY: Function('getRecentlyAddedItems')]
}
// [END_ENTITY: Repository('ItemRepositoryImpl')]
-// [ENTITY: Function('toDto')]
-// [RELATION: Function('toDto')] -> [RETURNS] -> [DataClass('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_ENTITY: Function('toDto')]
-
-// [ENTITY: Function('toDto')]
-// [RELATION: Function('toDto')] -> [RETURNS] -> [DataClass('LocationCreateDto')]
-private fun LocationCreate.toDto(): LocationCreateDto {
- return LocationCreateDto(
- name = this.name,
- color = this.color,
- description = null // Description is not part of the domain model for creation.
- )
-}
-// [END_ENTITY: Function('toDto')]
-
-// [ENTITY: Function('toDto')]
-// [RELATION: Function('toDto')] -> [RETURNS] -> [DataClass('LabelUpdateDto')]
-private fun LabelUpdate.toDto(): LabelUpdateDto {
- return LabelUpdateDto(
- name = this.name,
- color = this.color
- )
-}
-// [END_ENTITY: Function('toDto')]
-
// [END_FILE_ItemRepositoryImpl.kt]
\ No newline at end of file
diff --git a/domain/src/main/java/com/homebox/lens/domain/model/Item.kt b/domain/src/main/java/com/homebox/lens/domain/model/Item.kt
index 1c150f4..b0ee0b5 100644
--- a/domain/src/main/java/com/homebox/lens/domain/model/Item.kt
+++ b/domain/src/main/java/com/homebox/lens/domain/model/Item.kt
@@ -50,7 +50,7 @@ data class Item(
val image: String?,
val location: Location?,
val labels: List