feat: ajustar board de tickets
This commit is contained in:
parent
e9a8bd6b9b
commit
d23987eda8
7 changed files with 434 additions and 429 deletions
|
|
@ -72,6 +72,99 @@ const STATE_REGISTRATION_TYPE_FROM_PRISMA: Record<
|
|||
SIMPLES: "simples",
|
||||
}
|
||||
|
||||
const COMPANY_LEGACY_SELECT = {
|
||||
id: true,
|
||||
tenantId: true,
|
||||
name: true,
|
||||
slug: true,
|
||||
isAvulso: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
} satisfies Prisma.CompanySelect
|
||||
|
||||
type LegacyCompanyRow = Prisma.CompanyGetPayload<{ select: typeof COMPANY_LEGACY_SELECT }>
|
||||
|
||||
function isMissingProvisioningCodeColumn(error: unknown): boolean {
|
||||
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2022") {
|
||||
const meta = error.meta as Record<string, unknown> | undefined
|
||||
const metaColumn =
|
||||
typeof meta?.column === "string"
|
||||
? meta.column
|
||||
: typeof meta?.column_name === "string"
|
||||
? meta.column_name
|
||||
: typeof meta?.model === "string"
|
||||
? meta.model
|
||||
: null
|
||||
if (metaColumn && metaColumn.toLowerCase().includes("provisioningcode")) return true
|
||||
if (error.message.toLowerCase().includes("provisioningcode")) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export async function safeCompanyFindMany(args: Prisma.CompanyFindManyArgs): Promise<Company[]> {
|
||||
try {
|
||||
return await prisma.company.findMany(args)
|
||||
} catch (error) {
|
||||
if (!isMissingProvisioningCodeColumn(error)) {
|
||||
throw error
|
||||
}
|
||||
|
||||
if (args.select || args.include) {
|
||||
throw error
|
||||
}
|
||||
|
||||
const legacyRows = (await prisma.company.findMany({
|
||||
...args,
|
||||
select: COMPANY_LEGACY_SELECT,
|
||||
})) as LegacyCompanyRow[]
|
||||
|
||||
return legacyRows.map(
|
||||
(row) =>
|
||||
({
|
||||
id: row.id,
|
||||
tenantId: row.tenantId,
|
||||
name: row.name,
|
||||
slug: row.slug,
|
||||
provisioningCode: "",
|
||||
isAvulso: Boolean(row.isAvulso),
|
||||
contractedHoursPerMonth: null,
|
||||
cnpj: null,
|
||||
domain: null,
|
||||
phone: null,
|
||||
description: null,
|
||||
address: null,
|
||||
legalName: null,
|
||||
tradeName: null,
|
||||
stateRegistration: null,
|
||||
stateRegistrationType: null,
|
||||
primaryCnae: null,
|
||||
timezone: null,
|
||||
businessHours: Prisma.JsonNull,
|
||||
supportEmail: null,
|
||||
billingEmail: null,
|
||||
contactPreferences: Prisma.JsonNull,
|
||||
clientDomains: Prisma.JsonNull,
|
||||
communicationChannels: Prisma.JsonNull,
|
||||
fiscalAddress: Prisma.JsonNull,
|
||||
hasBranches: false,
|
||||
regulatedEnvironments: Prisma.JsonNull,
|
||||
privacyPolicyAccepted: false,
|
||||
privacyPolicyReference: null,
|
||||
privacyPolicyMetadata: Prisma.JsonNull,
|
||||
contacts: Prisma.JsonNull,
|
||||
locations: Prisma.JsonNull,
|
||||
contracts: Prisma.JsonNull,
|
||||
sla: Prisma.JsonNull,
|
||||
tags: Prisma.JsonNull,
|
||||
customFields: Prisma.JsonNull,
|
||||
notes: null,
|
||||
createdAt: row.createdAt,
|
||||
updatedAt: row.updatedAt,
|
||||
}) as Company
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export function formatZodError(error: ZodError) {
|
||||
return error.issues.map((issue) => ({
|
||||
path: issue.path.join("."),
|
||||
|
|
@ -328,171 +421,25 @@ export function normalizeCompany(company: Company): NormalizedCompany {
|
|||
return {
|
||||
...payload,
|
||||
id: company.id,
|
||||
provisioningCode: company.provisioningCode ?? null,
|
||||
provisioningCode: company.provisioningCode && company.provisioningCode.trim().length > 0
|
||||
? company.provisioningCode
|
||||
: null,
|
||||
createdAt: company.createdAt.toISOString(),
|
||||
updatedAt: company.updatedAt.toISOString(),
|
||||
}
|
||||
}
|
||||
|
||||
type RawCompanyRow = {
|
||||
id: string
|
||||
tenantId: string
|
||||
name: string
|
||||
slug: string
|
||||
provisioningCode: string | null
|
||||
isAvulso: number | boolean | null
|
||||
contractedHoursPerMonth: number | null
|
||||
cnpj: string | null
|
||||
domain: string | null
|
||||
phone: string | null
|
||||
description: string | null
|
||||
address: string | null
|
||||
legalName: string | null
|
||||
tradeName: string | null
|
||||
stateRegistration: string | null
|
||||
stateRegistrationType: string | null
|
||||
primaryCnae: string | null
|
||||
timezone: string | null
|
||||
businessHours: string | null
|
||||
supportEmail: string | null
|
||||
billingEmail: string | null
|
||||
contactPreferences: string | null
|
||||
clientDomains: string | null
|
||||
communicationChannels: string | null
|
||||
fiscalAddress: string | null
|
||||
hasBranches: number | null
|
||||
regulatedEnvironments: string | null
|
||||
privacyPolicyAccepted: number | null
|
||||
privacyPolicyReference: string | null
|
||||
privacyPolicyMetadata: string | null
|
||||
contacts: string | null
|
||||
locations: string | null
|
||||
contracts: string | null
|
||||
sla: string | null
|
||||
tags: string | null
|
||||
customFields: string | null
|
||||
notes: string | null
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
function parseJsonValue(value: string | null): Prisma.JsonValue | null {
|
||||
if (value === null || value === undefined) return null
|
||||
const trimmed = value.trim()
|
||||
if (!trimmed || trimmed.toLowerCase() === "null") return null
|
||||
try {
|
||||
return JSON.parse(trimmed) as Prisma.JsonValue
|
||||
} catch (error) {
|
||||
console.warn("[company-service] Invalid JSON detected; coercing to null.", { value, error })
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function mapRawRowToCompany(row: RawCompanyRow): Company {
|
||||
return {
|
||||
id: row.id,
|
||||
tenantId: row.tenantId,
|
||||
name: row.name,
|
||||
slug: row.slug,
|
||||
provisioningCode: row.provisioningCode ?? "",
|
||||
isAvulso: Boolean(row.isAvulso),
|
||||
contractedHoursPerMonth: row.contractedHoursPerMonth,
|
||||
cnpj: row.cnpj,
|
||||
domain: row.domain,
|
||||
phone: row.phone,
|
||||
description: row.description,
|
||||
address: row.address,
|
||||
legalName: row.legalName,
|
||||
tradeName: row.tradeName,
|
||||
stateRegistration: row.stateRegistration,
|
||||
stateRegistrationType: row.stateRegistrationType
|
||||
? (row.stateRegistrationType as DbCompanyStateRegistrationType)
|
||||
: null,
|
||||
primaryCnae: row.primaryCnae,
|
||||
timezone: row.timezone,
|
||||
businessHours: parseJsonValue(row.businessHours),
|
||||
supportEmail: row.supportEmail,
|
||||
billingEmail: row.billingEmail,
|
||||
contactPreferences: parseJsonValue(row.contactPreferences),
|
||||
clientDomains: parseJsonValue(row.clientDomains),
|
||||
communicationChannels: parseJsonValue(row.communicationChannels),
|
||||
fiscalAddress: parseJsonValue(row.fiscalAddress),
|
||||
hasBranches: Boolean(row.hasBranches),
|
||||
regulatedEnvironments: parseJsonValue(row.regulatedEnvironments),
|
||||
privacyPolicyAccepted: Boolean(row.privacyPolicyAccepted),
|
||||
privacyPolicyReference: row.privacyPolicyReference,
|
||||
privacyPolicyMetadata: parseJsonValue(row.privacyPolicyMetadata),
|
||||
contacts: parseJsonValue(row.contacts),
|
||||
locations: parseJsonValue(row.locations),
|
||||
contracts: parseJsonValue(row.contracts),
|
||||
sla: parseJsonValue(row.sla),
|
||||
tags: parseJsonValue(row.tags),
|
||||
customFields: parseJsonValue(row.customFields),
|
||||
notes: row.notes,
|
||||
createdAt: new Date(row.createdAt),
|
||||
updatedAt: new Date(row.updatedAt),
|
||||
}
|
||||
}
|
||||
|
||||
const COMPANY_BASE_SELECT = Prisma.sql`
|
||||
SELECT
|
||||
id,
|
||||
tenantId,
|
||||
name,
|
||||
slug,
|
||||
provisioningCode,
|
||||
isAvulso,
|
||||
contractedHoursPerMonth,
|
||||
cnpj,
|
||||
domain,
|
||||
phone,
|
||||
description,
|
||||
address,
|
||||
legalName,
|
||||
tradeName,
|
||||
stateRegistration,
|
||||
stateRegistrationType,
|
||||
primaryCnae,
|
||||
timezone,
|
||||
CAST(businessHours AS TEXT) AS businessHours,
|
||||
supportEmail,
|
||||
billingEmail,
|
||||
CAST(contactPreferences AS TEXT) AS contactPreferences,
|
||||
CAST(clientDomains AS TEXT) AS clientDomains,
|
||||
CAST(communicationChannels AS TEXT) AS communicationChannels,
|
||||
CAST(fiscalAddress AS TEXT) AS fiscalAddress,
|
||||
hasBranches,
|
||||
CAST(regulatedEnvironments AS TEXT) AS regulatedEnvironments,
|
||||
privacyPolicyAccepted,
|
||||
privacyPolicyReference,
|
||||
CAST(privacyPolicyMetadata AS TEXT) AS privacyPolicyMetadata,
|
||||
CAST(contacts AS TEXT) AS contacts,
|
||||
CAST(locations AS TEXT) AS locations,
|
||||
CAST(contracts AS TEXT) AS contracts,
|
||||
CAST(sla AS TEXT) AS sla,
|
||||
CAST(tags AS TEXT) AS tags,
|
||||
CAST(customFields AS TEXT) AS customFields,
|
||||
notes,
|
||||
createdAt,
|
||||
updatedAt
|
||||
FROM "Company"
|
||||
`
|
||||
|
||||
export async function fetchCompaniesByTenant(tenantId: string): Promise<Company[]> {
|
||||
const rows = await prisma.$queryRaw<RawCompanyRow[]>(Prisma.sql`
|
||||
${COMPANY_BASE_SELECT}
|
||||
WHERE tenantId = ${tenantId}
|
||||
ORDER BY name ASC
|
||||
`)
|
||||
return rows.map(mapRawRowToCompany)
|
||||
return safeCompanyFindMany({
|
||||
where: { tenantId },
|
||||
orderBy: { name: "asc" },
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchCompanyById(id: string): Promise<Company | null> {
|
||||
const rows = await prisma.$queryRaw<RawCompanyRow[]>(Prisma.sql`
|
||||
${COMPANY_BASE_SELECT}
|
||||
WHERE id = ${id}
|
||||
LIMIT 1
|
||||
`)
|
||||
const row = rows[0]
|
||||
return row ? mapRawRowToCompany(row) : null
|
||||
const rows = await safeCompanyFindMany({
|
||||
where: { id },
|
||||
take: 1,
|
||||
})
|
||||
return rows[0] ?? null
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue