hotfix-add subgroup customer

This commit is contained in:
phaichayon
2026-06-18 08:58:01 +07:00
parent 04a886ea26
commit 0650cf6297
38 changed files with 8674 additions and 687 deletions

View File

@@ -9,6 +9,7 @@ import {
lte,
ne,
or,
sql,
type SQL
} from 'drizzle-orm';
import {
@@ -32,6 +33,13 @@ interface NormalizedProjectParty {
roleCode: string;
}
type ProjectPartyTableAvailability = {
enquiryCustomers: boolean;
quotationCustomers: boolean;
};
let projectPartyTableAvailability: ProjectPartyTableAvailability | null = null;
function splitFilterValue(value?: string) {
return value
?.split(',')
@@ -152,11 +160,34 @@ function pickAttributedParties(
return authoritativeParties.filter((party) => party.roleCode === roleCode);
}
async function getProjectPartyTableAvailability(): Promise<ProjectPartyTableAvailability> {
if (projectPartyTableAvailability) {
return projectPartyTableAvailability;
}
const rows = await db.execute<{ tableName: string }>(sql`
select table_name as "tableName"
from information_schema.tables
where table_schema = 'public'
and table_name in ('crm_enquiry_customers', 'crm_quotation_customers')
`);
const available = new Set(rows.map((row) => row.tableName));
projectPartyTableAvailability = {
enquiryCustomers: available.has('crm_enquiry_customers'),
quotationCustomers: available.has('crm_quotation_customers')
};
return projectPartyTableAvailability;
}
async function getRevenueByRole(
organizationId: string,
roleCode: SupportedRevenueRole,
filters: RevenueAttributionFilters = {}
): Promise<RevenueAttributionSummary[]> {
const tableAvailability = await getProjectPartyTableAvailability();
const whereFilters = buildRevenueAttributionFilters(organizationId, filters);
const where = whereFilters.length === 1 ? whereFilters[0] : and(...whereFilters);
@@ -164,6 +195,7 @@ async function getRevenueByRole(
.select({
id: crmQuotations.id,
enquiryId: crmQuotations.enquiryId,
customerId: crmQuotations.customerId,
totalAmount: crmQuotations.totalAmount
})
.from(crmQuotations)
@@ -179,21 +211,23 @@ async function getRevenueByRole(
const [roleOptions, quotationParties, enquiryParties] = await Promise.all([
getActiveOptionsByCategory(PROJECT_PARTY_OPTION_CATEGORY, { organizationId }),
db
.select({
quotationId: crmQuotationCustomers.quotationId,
customerId: crmQuotationCustomers.customerId,
role: crmQuotationCustomers.role
})
.from(crmQuotationCustomers)
.where(
and(
eq(crmQuotationCustomers.organizationId, organizationId),
inArray(crmQuotationCustomers.quotationId, quotationIds),
isNull(crmQuotationCustomers.deletedAt)
)
),
enquiryIds.length
tableAvailability.quotationCustomers
? db
.select({
quotationId: crmQuotationCustomers.quotationId,
customerId: crmQuotationCustomers.customerId,
role: crmQuotationCustomers.role
})
.from(crmQuotationCustomers)
.where(
and(
eq(crmQuotationCustomers.organizationId, organizationId),
inArray(crmQuotationCustomers.quotationId, quotationIds),
isNull(crmQuotationCustomers.deletedAt)
)
)
: [],
tableAvailability.enquiryCustomers && enquiryIds.length
? db
.select({
enquiryId: crmEnquiryCustomers.enquiryId,
@@ -233,11 +267,16 @@ async function getRevenueByRole(
const attributionByQuotation = new Map<string, NormalizedProjectParty[]>();
for (const quotation of quotations) {
const attributedParties = pickAttributedParties(
roleCode,
quotationPartyMap.get(quotation.id) ?? [],
quotation.enquiryId ? (enquiryPartyMap.get(quotation.enquiryId) ?? []) : []
);
const quotationAttributedParties = quotationPartyMap.get(quotation.id) ?? [];
const enquiryAttributedParties = quotation.enquiryId
? (enquiryPartyMap.get(quotation.enquiryId) ?? [])
: [];
const attributedParties =
quotationAttributedParties.length > 0 || enquiryAttributedParties.length > 0
? pickAttributedParties(roleCode, quotationAttributedParties, enquiryAttributedParties)
: roleCode === 'end_customer' || roleCode === 'billing_customer'
? [{ customerId: quotation.customerId, roleCode }]
: [];
attributionByQuotation.set(quotation.id, attributedParties);