changes to import added activity entity

This commit is contained in:
Simon Pocrnjič
2025-12-16 19:35:51 +01:00
parent aa40ebed5c
commit a596177a68
9 changed files with 946 additions and 72 deletions
+126 -29
View File
@@ -26,6 +26,10 @@ const form = useForm({
// Add meta with default delimiter support
meta: {
...(props.template.meta || {}),
payments_import: props.template.meta?.payments_import ?? false,
history_import: props.template.meta?.history_import ?? false,
activity_action_id: props.template.meta?.activity_action_id ?? props.template.meta?.action_id ?? null,
activity_decision_id: props.template.meta?.activity_decision_id ?? props.template.meta?.decision_id ?? null,
delimiter: (props.template.meta && props.template.meta.delimiter) || "",
},
});
@@ -35,6 +39,21 @@ const decisionsForSelectedAction = vComputed(() => {
return act?.decisions || [];
});
const decisionsForActivitiesAction = vComputed(() => {
const act = (props.actions || []).find((a) => a.id === form.meta.activity_action_id);
return act?.decisions || [];
});
const activityCreatedAtInput = computed({
get() {
if (!form.meta.activity_created_at) return "";
return String(form.meta.activity_created_at).replace(" ", "T");
},
set(v) {
form.meta.activity_created_at = v ? String(v).replace("T", " ") : null;
},
});
vWatch(
() => form.meta.action_id,
() => {
@@ -42,6 +61,13 @@ vWatch(
}
);
vWatch(
() => form.meta.activity_action_id,
() => {
form.meta.activity_decision_id = null;
}
);
const entities = computed(() => props.template.meta?.entities || []);
const hasMappings = computed(() => (props.template.mappings?.length || 0) > 0);
const canChangeClient = computed(() => !hasMappings.value); // guard reassignment when mappings exist (optional rule)
@@ -67,6 +93,15 @@ const unassignedSourceColumns = computed(() => {
}
return Array.from(set).sort((a, b) => a.localeCompare(b));
});
const allSourceColumns = computed(() => {
const set = new Set();
(props.template.sample_headers || []).forEach((h) => set.add(h));
(props.template.mappings || []).forEach((m) => {
if (m.source_column) set.add(m.source_column);
});
return Array.from(set).sort((a, b) => a.localeCompare(b));
});
const unassignedState = ref({});
// Dynamic Import Entity definitions and field options from API
@@ -252,6 +287,11 @@ const save = () => {
// drop client change when blocked
delete payload.client_uuid;
}
const hasActivities = Array.isArray(payload.meta?.entities) && payload.meta.entities.includes('activities');
if (hasActivities && (!payload.meta?.activity_action_id || !payload.meta?.activity_decision_id)) {
alert('Activity imports require selecting an Action and Decision (Activities section).');
return;
}
// Normalize empty delimiter: remove from meta to allow auto-detect
if (
payload.meta &&
@@ -300,11 +340,27 @@ watch(
watch(
() => form.meta.payments_import,
(enabled) => {
if (enabled) {
if (form.meta.history_import) {
form.meta.history_import = false;
}
}
if (enabled && !form.meta.contract_key_mode) {
form.meta.contract_key_mode = "reference";
}
}
);
// History mode is mutually exclusive with payments mode
watch(
() => form.meta.history_import,
(enabled) => {
if (enabled && form.meta.payments_import) {
form.meta.payments_import = false;
form.meta.contract_key_mode = null;
}
}
);
</script>
<template>
@@ -423,7 +479,7 @@ watch(
</div>
<div>
<label class="block text-sm font-medium text-gray-700"
>Privzeto Dejanja (Activity)</label
>Privzeto Dejanja (post-contract activity)</label
>
<select
v-model="form.meta.action_id"
@@ -437,7 +493,7 @@ watch(
</div>
<div>
<label class="block text-sm font-medium text-gray-700"
>Privzeta Odločitev</label
>Privzeta Odločitev (post-contract)</label
>
<select
v-model="form.meta.decision_id"
@@ -484,22 +540,31 @@ watch(
</div>
</div>
<!-- Payments import toggle and settings -->
<!-- History / Payments import toggles and settings -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<div class="flex items-center gap-2">
<input
id="payments_import"
v-model="form.meta.payments_import"
type="checkbox"
class="rounded"
/>
<label for="payments_import" class="text-sm font-medium text-gray-700"
>Payments import</label
>
<div class="space-y-2">
<div class="flex items-center flex-wrap gap-4">
<label class="inline-flex items-center gap-2">
<input
id="history_import"
v-model="form.meta.history_import"
type="checkbox"
class="rounded"
/>
<span class="text-sm font-medium text-gray-700">History import</span>
</label>
<label class="inline-flex items-center gap-2">
<input
id="payments_import"
v-model="form.meta.payments_import"
type="checkbox"
class="rounded"
/>
<span class="text-sm font-medium text-gray-700">Payments import</span>
</label>
</div>
<p class="text-xs text-gray-500 mt-1">
When enabled, entities are locked to Contracts Accounts Payments.
<p class="text-xs text-gray-500">
History allows person/address/phone/contracts/activities/client cases; accounts are auto-added with contracts. Payments locks entities to Contracts Accounts Payments.
</p>
</div>
<div v-if="form.meta.payments_import">
@@ -856,6 +921,41 @@ watch(
<span class="text-xs text-gray-500">Klikni za razširitev</span>
</summary>
<div class="mt-4 space-y-4">
<div v-if="entity === 'activities'" class="grid grid-cols-1 sm:grid-cols-2 gap-4 p-3 bg-gray-50 rounded border">
<div>
<label class="block text-sm font-medium text-gray-700">Activity action *</label>
<select
v-model="form.meta.activity_action_id"
class="mt-1 block w-full border rounded p-2"
required
>
<option :value="null">(Select action)</option>
<option v-for="a in props.actions" :key="a.id" :value="a.id">{{ a.name }}</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Activity decision *</label>
<select
v-model="form.meta.activity_decision_id"
class="mt-1 block w-full border rounded p-2"
:disabled="!form.meta.activity_action_id"
required
>
<option :value="null">(Select decision)</option>
<option v-for="d in decisionsForActivitiesAction" :key="d.id" :value="d.id">{{ d.name }}</option>
</select>
<p v-if="!form.meta.activity_action_id" class="text-xs text-gray-500 mt-1">Choose an action first.</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Activity created at (override)</label>
<input
v-model="activityCreatedAtInput"
type="datetime-local"
class="mt-1 block w-full border rounded p-2"
/>
<p class="text-xs text-gray-500 mt-1">Optional: set a fixed timestamp for inserted activities (history imports).</p>
</div>
</div>
<!-- Existing mappings for this entity -->
<div
v-if="props.template.mappings && props.template.mappings.length"
@@ -954,22 +1054,19 @@ watch(
<div class="grid grid-cols-1 sm:grid-cols-6 gap-2 items-end">
<div>
<label class="block text-xs text-gray-600"
>Source column (ne-dodeljene)</label
>Source column (lahko uporabiš večkrat)</label
>
<select
<input
v-model="(newRows[entity] ||= {}).source"
class="mt-1 w-full border rounded p-2"
>
<option value="" disabled>(izberi)</option>
<option v-for="s in unassignedSourceColumns" :key="s" :value="s">
{{ s }}
</option>
</select>
<p
v-if="!unassignedSourceColumns.length"
class="text-xs text-gray-500 mt-1"
>
Ni nedodeljenih virov. Uporabi Bulk ali najprej dodaj vire.
list="src-opts-{{ entity }}"
placeholder="npr.: note, description"
/>
<datalist :id="`src-opts-${entity}`">
<option v-for="s in allSourceColumns" :key="s" :value="s">{{ s }}</option>
</datalist>
<p class="text-xs text-gray-500 mt-1">
Več stolpcev lahko povežeš na isto polje (npr. activity.note).
</p>
</div>
<div>