Wire real CiviCRM DEV custom fields and dynamic option fetching
This commit is contained in:
@@ -3,18 +3,18 @@
|
||||
*
|
||||
* Body: SubmitPayload { cid, cs, values }.
|
||||
*
|
||||
* Verifies checksum, resolves org from cid (same as /api/data), then creates a
|
||||
* new Org Engagement Submission activity with all visible-field values written
|
||||
* to their custom-field bindings + stage_at_submission set to the org's
|
||||
* current Framework Stage.
|
||||
* Verifies checksum, resolves org from cid (mirror of /api/data), then
|
||||
* creates a new `Check-in (organizing)` activity. The activity's own Stage
|
||||
* field (`Check_in_data__organizing_.Stage`) is auto-populated from the
|
||||
* org's current `Food_Co_op_Organizing.Stage` so each check-in carries a
|
||||
* snapshot of where the org was at submission time.
|
||||
*
|
||||
* STUB MODE: if CiviCRM env vars are unset, returns success without writing
|
||||
* anywhere. Useful for UI dev.
|
||||
* STUB MODE: if CiviCRM env vars are unset, returns success without writing.
|
||||
*/
|
||||
|
||||
import { NextResponse } from "next/server";
|
||||
import { civi, verifyChecksum } from "@/lib/civicrm";
|
||||
import { allFields } from "@/config/form";
|
||||
import { allFields, ACTIVITY_TYPE_NAME, ACTIVITY_STAGE_FIELD } from "@/config/form";
|
||||
import type { SubmitPayload } from "@/types/form";
|
||||
|
||||
function isStubMode(): boolean {
|
||||
@@ -40,16 +40,13 @@ export async function POST(req: Request) {
|
||||
}
|
||||
|
||||
if (isStubMode()) {
|
||||
console.warn("[submit:STUB] would create Org Engagement Submission activity with values:", values);
|
||||
console.warn("[submit:STUB] would create Check-in (organizing) activity with values:", values);
|
||||
return NextResponse.json({ ok: true, stub: true });
|
||||
}
|
||||
|
||||
const ok = await verifyChecksum(cid, cs);
|
||||
if (!ok) {
|
||||
return NextResponse.json(
|
||||
{ error: "Link is invalid or has expired." },
|
||||
{ status: 401 },
|
||||
);
|
||||
return NextResponse.json({ error: "Link is invalid or has expired." }, { status: 401 });
|
||||
}
|
||||
|
||||
// Resolve org via the relationship (mirror of /api/data).
|
||||
@@ -71,39 +68,37 @@ export async function POST(req: Request) {
|
||||
}
|
||||
const orgId = orgs[0].contact_id_b;
|
||||
|
||||
// Read the org's current Framework Stage so we can stamp `stage_at_submission`.
|
||||
const orgRes = await civi<{
|
||||
"Food_Co_op_Organizing.Stage": string | null;
|
||||
custom_1?: string | null;
|
||||
}>("Contact", "get", {
|
||||
select: ["custom_1", "Food_Co_op_Organizing.Stage"],
|
||||
where: [["id", "=", orgId]],
|
||||
});
|
||||
const stageAtSubmission =
|
||||
orgRes.values?.[0]?.["Food_Co_op_Organizing.Stage"] ??
|
||||
orgRes.values?.[0]?.custom_1 ??
|
||||
null;
|
||||
// Read the org's current Framework Stage so we can snapshot it on the activity.
|
||||
const orgRes = await civi<{ "Food_Co_op_Organizing.Stage": string | null }>(
|
||||
"Contact",
|
||||
"get",
|
||||
{
|
||||
select: ["Food_Co_op_Organizing.Stage"],
|
||||
where: [["id", "=", orgId]],
|
||||
},
|
||||
);
|
||||
const stageAtSubmission = orgRes.values?.[0]?.["Food_Co_op_Organizing.Stage"] ?? null;
|
||||
|
||||
// Build the activity record. Each form-side field name maps to its
|
||||
// configured `civiField` for the activity-side write.
|
||||
const activityRecord: Record<string, unknown> = {
|
||||
"activity_type_id:name": "Org Engagement Submission",
|
||||
"activity_type_id:name": ACTIVITY_TYPE_NAME,
|
||||
"status_id:name": "Completed",
|
||||
target_contact_id: orgId,
|
||||
source_contact_id: Number(cid),
|
||||
subject: "Co-op Check-in (form submission)",
|
||||
[ACTIVITY_STAGE_FIELD]: stageAtSubmission,
|
||||
};
|
||||
for (const [name, value] of Object.entries(values)) {
|
||||
const field = FIELD_BY_NAME.get(name);
|
||||
if (!field || !field.civiField) continue;
|
||||
if (field.type === "readonly") continue; // never write read-only fields
|
||||
if (name === "current_stage") continue; // org-side, never written to activity
|
||||
if (name === "stage_at_submission") continue; // handled above via ACTIVITY_STAGE_FIELD
|
||||
activityRecord[field.civiField] = value;
|
||||
}
|
||||
// Stamp the stage-at-submission audit field. Convention: a field named
|
||||
// `Submission_Audit.stage_at_submission` on the activity. Adjust to your
|
||||
// actual machine name if different.
|
||||
activityRecord["Submission_Audit.stage_at_submission"] = stageAtSubmission;
|
||||
|
||||
await civi("Activity", "create", { values: activityRecord });
|
||||
await civi("Activity", "create", { values: [activityRecord] });
|
||||
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user