fix: keep birthdays and show Shamsi dates
Imported customers keep their birthday, and assistant text plus remaining calendars use the Jalali date. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import {
|
||||
ConflictException,
|
||||
Injectable,
|
||||
Logger,
|
||||
NotFoundException,
|
||||
type OnModuleInit,
|
||||
} from '@nestjs/common';
|
||||
import type {
|
||||
CreatePersonRequest,
|
||||
@@ -32,6 +34,7 @@ import { AutomationsService } from '../automations/automations.service';
|
||||
import { MessageAutomationsService } from '../message-automations/message-automations.service';
|
||||
import { WebhooksService } from '../public-api/webhooks.service';
|
||||
import { GamificationService } from '../gamification/gamification.service';
|
||||
import { parseBirthDate } from '../common/excel';
|
||||
import { normalizeTags } from '../common/tags';
|
||||
import { buildSearchWhere, ci } from '../common/search';
|
||||
import {
|
||||
@@ -63,6 +66,7 @@ type PersonRow = {
|
||||
position: string | null;
|
||||
website: string | null;
|
||||
instagram: string | null;
|
||||
birthDate: Date | null;
|
||||
referrer: string | null;
|
||||
addresses: unknown;
|
||||
notes: string | null;
|
||||
@@ -83,7 +87,8 @@ type PersonRow = {
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class PeopleService {
|
||||
export class PeopleService implements OnModuleInit {
|
||||
private readonly logger = new Logger(PeopleService.name);
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly companies: CompaniesService,
|
||||
@@ -168,6 +173,71 @@ export class PeopleService {
|
||||
.sort((a, b) => b.count - a.count);
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
void this.backfillStoredBirthDates();
|
||||
}
|
||||
|
||||
/** تاریخ تولدی که قبلاً در فیلد اضافی دیدار/اکسل یا پروفایل مونتیفای مانده، روی شخص مینشیند. */
|
||||
async backfillStoredBirthDates() {
|
||||
try {
|
||||
const fromFields = await this.prisma.$queryRaw<Array<{ id: string; birth: string }>>`
|
||||
SELECT id,
|
||||
COALESCE(
|
||||
NULLIF("customFields"->>'birthDate', ''),
|
||||
NULLIF("customFields"->>'birthDate2', '')
|
||||
) AS birth
|
||||
FROM "Person"
|
||||
WHERE "birthDate" IS NULL
|
||||
AND (
|
||||
COALESCE("customFields"->>'birthDate', '') <> ''
|
||||
OR COALESCE("customFields"->>'birthDate2', '') <> ''
|
||||
)
|
||||
LIMIT 20000
|
||||
`;
|
||||
const fromMontify = await this.prisma.$queryRaw<Array<{ id: string; birth: string }>>`
|
||||
SELECT p.id, m.data->>'birthday' AS birth
|
||||
FROM "MontifyLink" m
|
||||
JOIN "Person" p ON p.id = m."entityId"
|
||||
WHERE m."entityType" = 'customer'
|
||||
AND p."birthDate" IS NULL
|
||||
AND COALESCE(m.data->>'birthday', '') <> ''
|
||||
LIMIT 20000
|
||||
`;
|
||||
const seen = new Set<string>();
|
||||
let filled = 0;
|
||||
for (const row of [...fromFields, ...fromMontify]) {
|
||||
if (!row.birth || seen.has(row.id)) continue;
|
||||
seen.add(row.id);
|
||||
const birthDate = parseBirthDate(row.birth);
|
||||
if (!birthDate) continue;
|
||||
const updated = await this.prisma.person.updateMany({
|
||||
where: { id: row.id, birthDate: null },
|
||||
data: { birthDate },
|
||||
});
|
||||
filled += updated.count;
|
||||
}
|
||||
if (filled) this.logger.log(`تاریخ تولد ${filled} مشتری از دادههای ذخیرهشده پر شد`);
|
||||
} catch (err) {
|
||||
this.logger.warn(
|
||||
`پر کردن تاریخ تولد ذخیرهشده ناموفق بود: ${err instanceof Error ? err.message : err}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async fillBirthDateIfEmpty(
|
||||
organizationId: string,
|
||||
input: { mobile?: string | null; email?: string | null; birthDate: Date },
|
||||
) {
|
||||
const or: Prisma.PersonWhereInput[] = [];
|
||||
if (input.mobile) or.push({ mobile: input.mobile });
|
||||
if (input.email) or.push({ email: input.email });
|
||||
if (!or.length) return;
|
||||
await this.prisma.person.updateMany({
|
||||
where: { organizationId, birthDate: null, OR: or },
|
||||
data: { birthDate: input.birthDate },
|
||||
});
|
||||
}
|
||||
|
||||
async get(actor: Actor, id: string): Promise<PersonDto> {
|
||||
const row = await this.prisma.person.findFirst({
|
||||
where: { id, organizationId: actor.organizationId, ...ownerWhere(actor) },
|
||||
@@ -198,6 +268,7 @@ export class PeopleService {
|
||||
position: emptyToNull(dto.position),
|
||||
website: emptyToNull(dto.website),
|
||||
instagram: emptyToNull(dto.instagram),
|
||||
birthDate: parseBirthDate(dto.birthDate),
|
||||
referrer: emptyToNull(dto.referrer),
|
||||
addresses: toJsonAddresses(dto.addresses),
|
||||
notes: emptyToNull(dto.notes),
|
||||
@@ -279,6 +350,7 @@ export class PeopleService {
|
||||
if ('position' in dto) data.position = emptyToNull(dto.position);
|
||||
if ('website' in dto) data.website = emptyToNull(dto.website);
|
||||
if ('instagram' in dto) data.instagram = emptyToNull(dto.instagram);
|
||||
if ('birthDate' in dto) data.birthDate = parseBirthDate(dto.birthDate);
|
||||
if ('referrer' in dto) data.referrer = emptyToNull(dto.referrer);
|
||||
if ('addresses' in dto) data.addresses = toJsonAddresses(dto.addresses);
|
||||
if ('notes' in dto) data.notes = emptyToNull(dto.notes);
|
||||
@@ -396,6 +468,7 @@ export class PeopleService {
|
||||
position: row.position,
|
||||
website: row.website,
|
||||
instagram: row.instagram,
|
||||
birthDate: row.birthDate?.toISOString() ?? null,
|
||||
referrer: row.referrer,
|
||||
addresses: (() => {
|
||||
const fromCol = asAddresses(row.addresses);
|
||||
|
||||
Reference in New Issue
Block a user