Changes to import and notifications
This commit is contained in:
@@ -82,6 +82,74 @@ const previewColumns = ref([]);
|
||||
const previewTruncated = ref(false);
|
||||
const previewLimit = ref(200);
|
||||
|
||||
// Import options (persisted on Import): show_missing and reactivate
|
||||
const showMissingEnabled = ref(Boolean(props.import?.show_missing ?? false));
|
||||
const reactivateEnabled = ref(Boolean(props.import?.reactivate ?? false));
|
||||
|
||||
async function saveImportOptions() {
|
||||
if (!importId.value) return;
|
||||
try {
|
||||
await axios.post(
|
||||
route("imports.options", { import: importId.value }),
|
||||
{
|
||||
show_missing: !!showMissingEnabled.value,
|
||||
// keep existing reactivate value if UI doesn't expose it here
|
||||
reactivate: !!reactivateEnabled.value,
|
||||
},
|
||||
{ headers: { Accept: "application/json" }, withCredentials: true }
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(
|
||||
"Save import options failed",
|
||||
e.response?.status || "",
|
||||
e.response?.data || e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Missing contracts (post-finish) UI state
|
||||
const showMissingContracts = ref(false);
|
||||
const missingContractsLoading = ref(false);
|
||||
const missingContracts = ref([]);
|
||||
const contractRefIsKeyref = computed(() => {
|
||||
return (persistedMappings.value || []).some((m) => {
|
||||
const tf = String(m?.target_field || "")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
const am = String(m?.apply_mode || "")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
return ["contract.reference", "contracts.reference"].includes(tf) && am === "keyref";
|
||||
});
|
||||
});
|
||||
const canShowMissingButton = computed(() => {
|
||||
return contractRefIsKeyref.value && !!showMissingEnabled.value;
|
||||
});
|
||||
async function openMissingContracts() {
|
||||
if (!importId.value || !contractRefIsKeyref.value) return;
|
||||
showMissingContracts.value = true;
|
||||
missingContractsLoading.value = true;
|
||||
try {
|
||||
const { data } = await axios.get(
|
||||
route("imports.missing-contracts", { import: importId.value }),
|
||||
{
|
||||
headers: { Accept: "application/json" },
|
||||
withCredentials: true,
|
||||
}
|
||||
);
|
||||
missingContracts.value = Array.isArray(data?.missing) ? data.missing : [];
|
||||
} catch (e) {
|
||||
console.error(
|
||||
"Missing contracts fetch failed",
|
||||
e.response?.status || "",
|
||||
e.response?.data || e
|
||||
);
|
||||
missingContracts.value = [];
|
||||
} finally {
|
||||
missingContractsLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if all detected columns are mapped with entity+field
|
||||
function evaluateMappingSaved() {
|
||||
console.log("here the evaluation happen of mapping save!");
|
||||
@@ -1028,6 +1096,11 @@ async function fetchSimulation() {
|
||||
:class="['px-2 py-0.5 rounded-full text-xs font-medium', statusInfo.classes]"
|
||||
>{{ statusInfo.label }}</span
|
||||
>
|
||||
<span
|
||||
v-if="showMissingEnabled"
|
||||
class="text-[10px] px-1 py-0.5 rounded bg-amber-100 text-amber-700 align-middle"
|
||||
>seznam manjkajočih</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1065,6 +1138,22 @@ async function fetchSimulation() {
|
||||
<span class="font-medium">{{ props.import?.valid_rows ?? "—" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3 flex items-center gap-2">
|
||||
<button
|
||||
class="px-3 py-1.5 bg-gray-700 text-white text-xs rounded"
|
||||
@click.prevent="openPreview"
|
||||
>
|
||||
Ogled CSV
|
||||
</button>
|
||||
<button
|
||||
v-if="canShowMissingButton"
|
||||
class="px-3 py-1.5 bg-indigo-600 text-white text-xs rounded"
|
||||
@click.prevent="openMissingContracts"
|
||||
title="Prikaži aktivne pogodbe, ki niso bile prisotne v uvozu (samo keyref)"
|
||||
>
|
||||
Ogled manjkajoče
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<TemplateControls
|
||||
@@ -1096,6 +1185,24 @@ async function fetchSimulation() {
|
||||
"
|
||||
@apply-template="applyTemplateToImport"
|
||||
/>
|
||||
<!-- Import options -->
|
||||
<div v-if="!isCompleted" class="mt-2 p-3 rounded border bg-gray-50">
|
||||
<div class="flex items-center gap-3">
|
||||
<label class="inline-flex items-center text-sm text-gray-700">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="rounded mr-2"
|
||||
v-model="showMissingEnabled"
|
||||
@change="saveImportOptions"
|
||||
/>
|
||||
<span>Seznam manjkajočih (po končanem uvozu)</span>
|
||||
</label>
|
||||
</div>
|
||||
<p class="mt-1 text-xs text-gray-500">
|
||||
Ko je omogočeno in je "contract.reference" nastavljen na keyref, bo po
|
||||
končanem uvozu na voljo gumb za ogled pogodb, ki jih ni v datoteki.
|
||||
</p>
|
||||
</div>
|
||||
<ChecklistSteps :steps="stepStates" :missing-critical="missingCritical" />
|
||||
</div>
|
||||
|
||||
@@ -1173,6 +1280,57 @@ async function fetchSimulation() {
|
||||
@change-limit="(val) => (previewLimit = val)"
|
||||
@refresh="fetchPreview"
|
||||
/>
|
||||
<!-- Missing contracts modal -->
|
||||
<Modal
|
||||
:show="showMissingContracts"
|
||||
max-width="2xl"
|
||||
@close="showMissingContracts = false"
|
||||
>
|
||||
<div class="p-4 max-h-[70vh] overflow-auto">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="font-semibold text-lg">Manjkajoče pogodbe (aktivne, ne-arhivirane)</h3>
|
||||
<button
|
||||
class="text-gray-500 hover:text-gray-700"
|
||||
@click.prevent="showMissingContracts = false"
|
||||
>
|
||||
Zapri
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="missingContractsLoading" class="py-8 text-center text-sm text-gray-500">
|
||||
Nalagam …
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="!missingContracts.length" class="py-6 text-sm text-gray-600">
|
||||
Ni zadetkov.
|
||||
</div>
|
||||
<ul v-else class="divide-y divide-gray-200">
|
||||
<li
|
||||
v-for="row in missingContracts"
|
||||
:key="row.uuid"
|
||||
class="py-2 text-sm flex items-center justify-between"
|
||||
>
|
||||
<div class="min-w-0">
|
||||
<div class="font-mono text-gray-800">{{ row.reference }}</div>
|
||||
<div class="text-xs text-gray-500 truncate">
|
||||
<span class="font-medium text-gray-600">Primer: </span>
|
||||
<span>{{ row.full_name || "—" }}</span>
|
||||
<span v-if="row.balance_amount != null" class="ml-2"
|
||||
>• {{ formatMoney(row.balance_amount) }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-shrink-0">
|
||||
<a
|
||||
:href="route('clientCase.show', row.case_uuid)"
|
||||
class="text-blue-600 hover:underline text-xs"
|
||||
>Odpri primer</a
|
||||
>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<SimulationModal
|
||||
:show="showPaymentSim"
|
||||
:rows="paymentSimRows"
|
||||
|
||||
@@ -11,10 +11,21 @@ const props = defineProps({
|
||||
limit: { type: Number, default: 50 },
|
||||
loading: { type: Boolean, default: false },
|
||||
entities: { type: Array, default: () => [] },
|
||||
// passthrough verbose from parent to render extra sources in table
|
||||
verbose: { type: Boolean, default: false },
|
||||
});
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits(["close", "update:limit"]);
|
||||
const emit = defineEmits(["close", "update:limit", "toggle-verbose"]);
|
||||
|
||||
// Local handlers for header controls
|
||||
function onLimit(e) {
|
||||
const val = Number(e?.target?.value ?? props.limit ?? 50);
|
||||
emit("update:limit", isNaN(val) ? 50 : val);
|
||||
}
|
||||
function toggleVerbose() {
|
||||
emit("toggle-verbose");
|
||||
}
|
||||
|
||||
// Map technical entity keys to localized labels
|
||||
const entityLabelMap = {
|
||||
@@ -70,6 +81,8 @@ const entitiesWithRows = computed(() => {
|
||||
const activeEntity = ref(null);
|
||||
const hideChain = ref(false);
|
||||
const showOnlyChanged = ref(false);
|
||||
// Show only rows skipped due to missing contract.reference in keyref mode (contract/account)
|
||||
const showOnlyKeyrefSkipped = ref(false);
|
||||
watch(
|
||||
entitiesWithRows,
|
||||
(val) => {
|
||||
@@ -156,6 +169,15 @@ const visibleRows = computed(() => {
|
||||
.filter((r) => {
|
||||
if (!r.entities || !r.entities[activeEntity.value]) return false;
|
||||
const ent = r.entities[activeEntity.value];
|
||||
// Filter: only rows explicitly skipped due to keyref missing
|
||||
if (showOnlyKeyrefSkipped.value) {
|
||||
if (Array.isArray(ent)) {
|
||||
const anySkipped = ent.some((i) => i && i.skipped_due_to_keyref);
|
||||
if (!anySkipped) return false;
|
||||
} else {
|
||||
if (!ent.skipped_due_to_keyref) return false;
|
||||
}
|
||||
}
|
||||
if (!Array.isArray(ent)) {
|
||||
if (hideChain.value && ent.existing_chain) return false;
|
||||
}
|
||||
@@ -286,7 +308,7 @@ function referenceOf(entityName, ent) {
|
||||
class="text-[11px] px-2 py-1 rounded border bg-white hover:bg-gray-50"
|
||||
@click="toggleVerbose"
|
||||
>
|
||||
{{ verbose ? "Manj" : "Več" }} podrobnosti
|
||||
{{ props.verbose ? "Manj" : "Več" }} podrobnosti
|
||||
</button>
|
||||
<label class="flex items-center gap-1 text-[11px] text-gray-600">
|
||||
<input type="checkbox" v-model="hideChain" class="rounded border-gray-300" />
|
||||
@@ -300,6 +322,14 @@ function referenceOf(entityName, ent) {
|
||||
/>
|
||||
Samo spremenjeni
|
||||
</label>
|
||||
<label class="flex items-center gap-1 text-[11px] text-gray-600" title="Prikaži le vrstice preskočene zaradi manjkajoče contract.reference v načinu keyref (pogodbe/računi)">
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="showOnlyKeyrefSkipped"
|
||||
class="rounded border-gray-300"
|
||||
/>
|
||||
Samo preskočene (keyref)
|
||||
</label>
|
||||
<button
|
||||
type="button"
|
||||
class="text-[11px] px-2 py-1 rounded bg-gray-800 text-white hover:bg-gray-700"
|
||||
|
||||
Reference in New Issue
Block a user