Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08f164a209 | ||
|
|
23450bb6d0 | ||
|
|
20ccba5292 |
@@ -12,8 +12,8 @@ android {
|
|||||||
applicationId = "com.korexlabs.dhinspeccion"
|
applicationId = "com.korexlabs.dhinspeccion"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 33
|
versionCode = 34
|
||||||
versionName = "0.19.5"
|
versionName = "0.19.6"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.focus.FocusDirection
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
@@ -778,6 +779,11 @@ private fun ModernFieldInventoryScreen(model: MainViewModel, onBack: () -> Unit)
|
|||||||
enabled = !model.busy,
|
enabled = !model.busy,
|
||||||
modifier = Modifier.fillMaxWidth().menuAnchor(MenuAnchorType.PrimaryEditable),
|
modifier = Modifier.fillMaxWidth().menuAnchor(MenuAnchorType.PrimaryEditable),
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
||||||
|
keyboardActions = KeyboardActions(onNext = {
|
||||||
|
familyExpanded = false
|
||||||
|
focusManager.moveFocus(FocusDirection.Down)
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
ExposedDropdownMenu(
|
ExposedDropdownMenu(
|
||||||
expanded = familyExpanded && !model.busy,
|
expanded = familyExpanded && !model.busy,
|
||||||
@@ -818,9 +824,11 @@ private fun ModernFieldInventoryScreen(model: MainViewModel, onBack: () -> Unit)
|
|||||||
value = name,
|
value = name,
|
||||||
onValueChange = { name = it },
|
onValueChange = { name = it },
|
||||||
label = { Text("Nombre técnico *") },
|
label = { Text("Nombre técnico *") },
|
||||||
supportingText = { Text("Usá la denominación técnica del elemento. El código DH se genera automáticamente.") },
|
placeholder = { Text("Denominación técnica") },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
||||||
|
keyboardActions = KeyboardActions(onNext = { focusManager.moveFocus(FocusDirection.Down) }),
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = commonName,
|
value = commonName,
|
||||||
@@ -828,17 +836,24 @@ private fun ModernFieldInventoryScreen(model: MainViewModel, onBack: () -> Unit)
|
|||||||
label = { Text("Nombre habitual (opcional)") },
|
label = { Text("Nombre habitual (opcional)") },
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
||||||
|
keyboardActions = KeyboardActions(onNext = { focusManager.moveFocus(FocusDirection.Down) }),
|
||||||
)
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = description,
|
value = description,
|
||||||
onValueChange = { description = it },
|
onValueChange = { description = it },
|
||||||
label = { Text("Descripción (opcional)") },
|
label = { Text("Descripción (opcional)") },
|
||||||
supportingText = { Text("Dato equivalente al alta desde el panel web.") },
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
minLines = 2,
|
singleLine = true,
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = if (editableAttributes.isEmpty()) ImeAction.Done else ImeAction.Next),
|
||||||
|
keyboardActions = KeyboardActions(
|
||||||
|
onNext = { focusManager.moveFocus(FocusDirection.Down) },
|
||||||
|
onDone = { keyboard?.hide(); focusManager.clearFocus() },
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
editableAttributes.forEach { definition ->
|
editableAttributes.forEachIndexed { index, definition ->
|
||||||
|
val isLastAttribute = index == editableAttributes.lastIndex
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = attributeValues[definition.code].orEmpty(),
|
value = attributeValues[definition.code].orEmpty(),
|
||||||
onValueChange = { attributeValues[definition.code] = it },
|
onValueChange = { attributeValues[definition.code] = it },
|
||||||
@@ -849,8 +864,14 @@ private fun ModernFieldInventoryScreen(model: MainViewModel, onBack: () -> Unit)
|
|||||||
},
|
},
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
keyboardType = if (definition.dataType.uppercase() in setOf("NUMBER", "DECIMAL", "INTEGER", "FLOAT")) KeyboardType.Decimal else KeyboardType.Text,
|
keyboardType = if (definition.dataType.uppercase() in setOf("NUMBER", "DECIMAL", "INTEGER", "FLOAT")) KeyboardType.Decimal else KeyboardType.Text,
|
||||||
|
imeAction = if (isLastAttribute) ImeAction.Done else ImeAction.Next,
|
||||||
|
),
|
||||||
|
keyboardActions = KeyboardActions(
|
||||||
|
onNext = { focusManager.moveFocus(FocusDirection.Down) },
|
||||||
|
onDone = { keyboard?.hide(); focusManager.clearFocus() },
|
||||||
),
|
),
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
singleLine = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 8.2 KiB |
@@ -8,8 +8,8 @@ class ReleaseMetadataTest {
|
|||||||
@Test
|
@Test
|
||||||
fun debugBuildKeepsSeparateApplicationIdentity() {
|
fun debugBuildKeepsSeparateApplicationIdentity() {
|
||||||
assertEquals("com.korexlabs.dhinspeccion.debug", BuildConfig.APPLICATION_ID)
|
assertEquals("com.korexlabs.dhinspeccion.debug", BuildConfig.APPLICATION_ID)
|
||||||
assertEquals(33, BuildConfig.VERSION_CODE)
|
assertEquals(34, BuildConfig.VERSION_CODE)
|
||||||
assertEquals("0.19.5-debug", BuildConfig.VERSION_NAME)
|
assertEquals("0.19.6-debug", BuildConfig.VERSION_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -760,6 +760,7 @@ export class AssetsService {
|
|||||||
parentId: dto.parentId,
|
parentId: dto.parentId,
|
||||||
operationalAreaId: dto.operationalAreaId,
|
operationalAreaId: dto.operationalAreaId,
|
||||||
operatorCompanyId: dto.operatorCompanyId,
|
operatorCompanyId: dto.operatorCompanyId,
|
||||||
|
inventoryFamilyId: dto.inventoryFamilyId ?? null,
|
||||||
code: dto.code,
|
code: dto.code,
|
||||||
name: dto.name,
|
name: dto.name,
|
||||||
commonName: dto.commonName ?? null,
|
commonName: dto.commonName ?? null,
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ export class CreateFieldDiscoveryDto {
|
|||||||
@IsUUID('4')
|
@IsUUID('4')
|
||||||
operatorCompanyId!: string;
|
operatorCompanyId!: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsUUID('4')
|
||||||
|
inventoryFamilyId?: string | null;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@Transform(({ value }) => typeof value === 'string' && value.trim() ? value.trim() : null)
|
@Transform(({ value }) => typeof value === 'string' && value.trim() ? value.trim() : null)
|
||||||
@IsString()
|
@IsString()
|
||||||
|
|||||||
@@ -295,6 +295,7 @@ export class FieldInventoryService {
|
|||||||
operationalAreaId: context.areaId,
|
operationalAreaId: context.areaId,
|
||||||
// Compatibility-only creation snapshot. Membership never depends on it.
|
// Compatibility-only creation snapshot. Membership never depends on it.
|
||||||
operatorCompanyId: context.companyId,
|
operatorCompanyId: context.companyId,
|
||||||
|
inventoryFamilyId: dto.familyId ?? null,
|
||||||
description: dto.description ?? null,
|
description: dto.description ?? null,
|
||||||
discoveryNotes: dto.discoveryNotes ?? null,
|
discoveryNotes: dto.discoveryNotes ?? null,
|
||||||
attributes: dto.attributes,
|
attributes: dto.attributes,
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ function mountedRepoFile(path: string): string {
|
|||||||
test('F6.3 Android test cut targets production API and has a distinct installable debug version', () => {
|
test('F6.3 Android test cut targets production API and has a distinct installable debug version', () => {
|
||||||
const gradle = mountedRepoFile('android-app/app/build.gradle.kts');
|
const gradle = mountedRepoFile('android-app/app/build.gradle.kts');
|
||||||
|
|
||||||
assert.match(gradle, /versionCode = 33/);
|
assert.match(gradle, /versionCode = 34/);
|
||||||
assert.match(gradle, /versionName = "0\.19\.5"/);
|
assert.match(gradle, /versionName = "0\.19\.6"/);
|
||||||
assert.match(gradle, /https:\/\/dhv2\.korexlabs\.com\/api\/v3\//);
|
assert.match(gradle, /https:\/\/dhv2\.korexlabs\.com\/api\/v3\//);
|
||||||
assert.match(gradle, /applicationIdSuffix = "\.debug"/);
|
assert.match(gradle, /applicationIdSuffix = "\.debug"/);
|
||||||
});
|
});
|
||||||
@@ -26,3 +26,18 @@ test('F5/F6.3 field inventory exposes Other families as reviewable choices to An
|
|||||||
assert.match(service, /AS "isOther"/);
|
assert.match(service, /AS "isOther"/);
|
||||||
assert.match(service, /isOtherFamily: family\.isOther/);
|
assert.match(service, /isOtherFamily: family\.isOther/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('field inventory persists the validated Tipo de instalación in the initial asset insert', () => {
|
||||||
|
const fieldService = readFileSync(
|
||||||
|
resolve(process.cwd(), 'src/inspection-visits/field-inventory.service.ts'),
|
||||||
|
'utf8',
|
||||||
|
);
|
||||||
|
const assetsService = readFileSync(
|
||||||
|
resolve(process.cwd(), 'src/asset-master/assets.service.ts'),
|
||||||
|
'utf8',
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.match(fieldService, /inventoryFamilyId: dto\.familyId \?\? null/);
|
||||||
|
assert.match(assetsService, /inventoryFamilyId: dto\.inventoryFamilyId \?\? null/);
|
||||||
|
});
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ WORKDIR /app
|
|||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
RUN npm ci
|
RUN npm ci
|
||||||
COPY tsconfig*.json vite.config.ts index.html ./
|
COPY tsconfig*.json vite.config.ts index.html ./
|
||||||
|
COPY public ./public
|
||||||
COPY src ./src
|
COPY src ./src
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta name="referrer" content="strict-origin-when-cross-origin" />
|
<meta name="referrer" content="strict-origin-when-cross-origin" />
|
||||||
|
<link rel="icon" type="image/webp" href="/favicon.webp" />
|
||||||
<title>DH Inspección V2</title>
|
<title>DH Inspección V2</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
Reference in New Issue
Block a user