feat(admin): birth date on the customer forms; permission saves limited to known rids (PERS-03, SEC-07)
- PERS-03: «تاریخ تولد» (Jalali DateInput) on the wholesale and retail forms, as legacy. The server accepts birth_date or birth_day, refuses impossible or future dates, clears on '', and returns both names. - SEC-07: setRoles stores only rids in ALL_RIDS or their tree parents. Anything else is dropped with a warning log, so a tick on a legacy-only tree leaf never fails the save. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
7bb5c2e00f
commit
d91dcf197b
@@ -10,8 +10,9 @@
|
||||
render this component directly as a route-based fallback, but OmdeList.vue
|
||||
now opens it as a modal via open/id props.
|
||||
|
||||
Dropped: the MyUpload avatar widget and the Jalali DateInput, which belong to
|
||||
fields the redesigned Customer schema has no column for. Flagged in
|
||||
«تاریخ تولد» (legacy's Jalali DateInput, birth_date) is back since the
|
||||
Customer schema has birthDate (PERS-03). Dropped: the MyUpload avatar widget,
|
||||
which belongs to a field the redesigned Customer schema has no column for. Flagged in
|
||||
docs/ADMIN-PORT-PLAN.md rather than faked.
|
||||
|
||||
The نوع کاربری selector is live again now that Customer.type exists; its four
|
||||
@@ -79,6 +80,11 @@
|
||||
<a-form-item label="کد مشتری">
|
||||
<a-input v-model:value="form.mcode" />
|
||||
</a-form-item>
|
||||
<DateInput
|
||||
:model-value="form.birth_date || undefined"
|
||||
label="تاریخ تولد"
|
||||
@update:model-value="(v) => (form.birth_date = v ?? '')"
|
||||
/>
|
||||
<a-form-item label="کارشناس فروش">
|
||||
<a-select v-model:value="form.reagent_id" allow-clear placeholder="انتخاب کنید">
|
||||
<a-select-option v-for="r in reagent" :key="r.id" :value="r.id">
|
||||
@@ -182,6 +188,11 @@
|
||||
<a-form-item label="کد مشتری">
|
||||
<a-input v-model:value="form.mcode" />
|
||||
</a-form-item>
|
||||
<DateInput
|
||||
:model-value="form.birth_date || undefined"
|
||||
label="تاریخ تولد"
|
||||
@update:model-value="(v) => (form.birth_date = v ?? '')"
|
||||
/>
|
||||
<a-form-item label="کارشناس فروش">
|
||||
<a-select v-model:value="form.reagent_id" allow-clear placeholder="انتخاب کنید">
|
||||
<a-select-option v-for="r in reagent" :key="r.id" :value="r.id">
|
||||
@@ -250,6 +261,7 @@ import BaseFormModal from '../../../components/common/BaseFormModal.vue';
|
||||
import ImageUploadInput from '../../../components/upload/ImageUploadInput.vue';
|
||||
import api from '../../../api/client';
|
||||
import CityTreeSelect from '../../../components/common/CityTreeSelect.vue';
|
||||
import DateInput from '../../../components/input/DateInput.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
open?: boolean;
|
||||
@@ -294,6 +306,7 @@ const form = reactive<Record<string, any>>({
|
||||
pasazh_name: '',
|
||||
city_id: undefined,
|
||||
mcode: '',
|
||||
birth_date: '',
|
||||
address: '',
|
||||
// legacy defaulted to no selection; 2 (مغازه دار اپلیکیشن) is what the
|
||||
// backend falls back to when the field is absent.
|
||||
@@ -465,6 +478,7 @@ onMounted(async () => {
|
||||
store_name: data.store_name ?? '',
|
||||
pasazh_name: data.pasazh_name ?? '',
|
||||
mcode: data.mcode ?? '',
|
||||
birth_date: data.birth_date ?? '',
|
||||
phone: data.phone ?? '',
|
||||
type: data.type ?? undefined,
|
||||
// Same reason as the five above: omitted here, they would be sent back
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
<a-form-item label="شهر">
|
||||
<CityTreeSelect v-model:value="form.city_id" :cities="cities" />
|
||||
</a-form-item>
|
||||
<DateInput
|
||||
:model-value="form.birth_day || undefined"
|
||||
label="تاریخ تولد"
|
||||
@update:model-value="(v) => (form.birth_day = v ?? '')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<a-button type="primary" @click="handleSubmit">ثبت اطلاعات</a-button>
|
||||
@@ -48,6 +53,7 @@ import { useRoute, useRouter } from 'vue-router';
|
||||
import { message } from 'ant-design-vue';
|
||||
import api from '../../../api/client';
|
||||
import CityTreeSelect from '../../../components/common/CityTreeSelect.vue';
|
||||
import DateInput from '../../../components/input/DateInput.vue';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@@ -61,6 +67,7 @@ const form = reactive<Record<string, any>>({
|
||||
lname: '',
|
||||
phone: '',
|
||||
city_id: undefined,
|
||||
birth_day: '',
|
||||
});
|
||||
const err = reactive<Record<string, string>>({});
|
||||
const REQUIRED = 'لطفا مقدار را وارد کنید';
|
||||
@@ -115,6 +122,7 @@ onMounted(async () => {
|
||||
lname: data.lname ?? '',
|
||||
phone: data.mobile ?? '',
|
||||
city_id: data.city_id ?? undefined,
|
||||
birth_day: data.birth_day ?? '',
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
|
||||
Reference in New Issue
Block a user