Open Shaik-Sirajuddin opened 5 months ago
To create a managed event type for team members via the API v1 without encountering the "Admin required" error, ensure the following:
teamId
in the request body.Here is an example of a request body for creating a team event type:
{
"title": "Tennis class",
"slug": "tennis-class-{{$guid}}",
"length": 60,
"hidden": false,
"position": 0,
"teamId": 3,
"requiresConfirmation": true,
"schedulingType": "MANAGED",
"price": 0,
"currency": "usd",
"description": "A test event type",
"metadata": {}
}
Ensure that the user making this request has the necessary permissions to access the team with the specified teamId
.
Additionally, you can refer to the following test case to understand how managed event types are created and managed in the system:
import type { Page } from "@playwright/test";
import { expect } from "@playwright/test";
import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants";
import { test } from "./lib/fixtures";
import {
bookTimeSlot,
fillStripeTestCheckout,
localize,
selectFirstAvailableTimeSlotNextMonth,
} from "./lib/testUtils";
test.afterAll(({ users }) => users.deleteAll());
test.describe("Managed Event Types", () => {
test("Can create managed event type", async ({ page, users }) => {
// Creating the owner user of the team
const adminUser = await users.create();
// Creating the member user of the team
const memberUser = await users.create();
// First we work with owner user, logging in
await adminUser.apiLogin();
// Let's create a team
await page.goto("/settings/teams/new");
await test.step("Managed event option exists for team admin", async () => {
// Filling team creation form wizard
await page.locator('input[name="name"]').fill(`${adminUser.username}'s Team`);
await page.click("[type=submit]");
if (IS_TEAM_BILLING_ENABLED) await fillStripeTestCheckout(page);
await page.waitForURL(/\/settings\/teams\/(\d+)\/onboard-members.*$/i);
await page.getByTestId("new-member-button").click();
await page.locator('[placeholder="email\\@example\\.com"]').fill(`${memberUser.username}@example.com`);
await page.getByTestId("invite-new-member-button").click();
await page.getByTestId("pending-member-list").locator("li:nth-child(2)").waitFor();
await page.locator("[data-testid=publish-button]").click();
await expect(page).toHaveURL(/\/settings\/teams\/(\d+)\/profile$/i);
await page.goto("/event-types");
await page.getByTestId("new-event-type").click();
await page.getByTestId("option-team-1").click();
await expect(page.locator('button[value="MANAGED"]')).toBeVisible();
await page.click('button[value="MANAGED"]');
await page.fill("[name=title]", "managed");
await page.click("[type=submit]");
await page.waitForURL("event-types/**");
});
await test.step("Managed event type has unlocked fields for admin", async () => {
await page.getByTestId("update-eventtype").waitFor();
await expect(page.locator('input[name="title"]')).toBeEditable();
await expect(page.locator('input[name="slug"]')).toBeEditable();
await expect(page.locator('input[name="length"]')).toBeEditable();
await adminUser.apiLogin();
});
await test.step("Managed event type exists for added member", async () => {
await memberUser.apiLogin();
await page.goto("/teams");
await page.locator('button[data-testid^="accept-invitation"]').click();
await page.getByText("Member").waitFor();
await page.goto("/auth/logout");
await adminUser.apiLogin();
await page.goto("/event-types");
await page.getByTestId("event-types").locator('a[title="managed"]').click();
await page.getByTestId("vertical-tab-assignment").click();
await page.getByTestId("assignment-dropdown").click();
await page.getByTestId(`select-option-${memberUser.id}`).click();
await page.locator('[type="submit"]').click();
await page.getByTestId("toast-success").waitFor();
});
await test.step("Managed event type can use Organizer's default app as location", async () => {
await page.getByTestId("vertical-tab-event_setup_tab_title").click();
await page.locator("#location-select").click();
const optionText = (await localize("en"))("organizer_default_conferencing_app");
await page.locator(`text=${optionText}`).click();
await page.locator("[data-testid=update-eventtype]").click();
await page.getByTestId("toast-success").waitFor();
await page.waitForLoadState("networkidle");
await page.getByTestId("vertical-tab-assignment").click();
await gotoBookingPage(page);
await selectFirstAvailableTimeSlotNextMonth(page);
await bookTimeSlot(page);
await expect(page.getByTestId("success-page")).toBeVisible();
});
await test.step("Managed event type has locked fields for added member", async () => {
await adminUser.logout();
await memberUser.apiLogin();
await page.goto("/event-types");
await page.getByTestId("event-types").locator('a[title="managed"]').click();
await page.waitForURL("event-types/**");
await expect(page.locator('input[name="title"]')).not.toBeEditable();
await expect(page.locator('input[name="slug"]')).not.toBeEditable();
await expect(page.locator('input[name="length"]')).not toBeEditable();
await page.goto("/auth/logout");
});
await test.step("Managed event type provides discrete field lock/unlock state for admin", async () => {
await adminUser.apiLogin();
await page.goto("/event-types");
await page.getByTestId("event-types").locator('a[title="managed"]').click();
await page.waitForURL("event-types/**");
const titleLockIndicator = page.getByTestId("locked-indicator-title");
await expect(titleLockIndicator).toBeVisible();
await expect(titleLockIndicator.locator("[data-state='checked']")).toHaveCount(1);
titleLockIndicator.click();
await expect(titleLockIndicator.locator("[data-state='checked']")).toHaveCount(0);
await expect(titleLockIndicator.locator("[data-state='unchecked']")).toHaveCount(1);
await page.locator('[type="submit"]').click();
await page.waitForLoadState("networkidle");
await page.goto("/auth/logout");
});
await test.step("Managed event type shows discretionally unlocked field to member", async () => {
await memberUser.apiLogin();
await page.goto("/event-types");
await page.getByTestId("event-types").locator('a[title="managed"]').click();
await page.waitForURL("event-types/**");
await expect(page.locator('input[name="title"]')).toBeEditable();
await page.waitForLoadState("networkidle");
await page.goto("/auth/logout");
});
await test.step("Managed event type should only update the unlocked fields modified by Admin", async () => {
await memberUser.apiLogin();
await page.goto("/event-types");
await page.getByTestId("event-types").locator('a[title="managed"]').click();
await page.waitForURL("event-types/**");
await expect(page.locator('input[name="title"]')).toBeEditable();
await page.locator('input[name="title"]').fill(`Managed Event Title`);
await page.locator('[type="submit"]').click();
await page.getByTestId("toast-success").waitFor();
await page.waitForLoadState("networkidle");
await page.goto("/auth/logout");
await adminUser.apiLogin();
await page.goto("/event-types");
await page.getByTestId("event-types").locator('a[title="managed"]').click();
await page.waitForURL("event-types/**");
await page.locator('input[name="length"]').fill(`45`);
await page.locator('[type="submit"]').click();
await page.getByTestId("toast-success").waitFor();
await page.waitForLoadState("networkidle");
await page.goto("/auth/logout");
await memberUser.apiLogin();
await page.goto("/event-types");
await page.getByTestId("event-types").locator('a[title="Managed Event Title"]').click();
await page.waitForURL("event-types/**");
expect(await page.locator("[data-testid=duration]").getAttribute("value")).toBe("45");
expect(await page.locator(`input[name="title"]`).getAttribute("value")).toBe(`Managed Event Title`);
await page.locator('input[name="title"]').fill(`managed`);
await page.locator('[type="submit"]').click();
await page.getByTestId("toast-success").waitFor();
});
});
});
async function gotoBookingPage(page: Page) {
const previewLink = await page.getByTestId("preview-button").getAttribute("href");
await page.goto(previewLink ?? "");
}
This test case demonstrates the process of creating a managed event type, assigning it to team members, and verifying the permissions and field lock/unlock states.
To continue the conversation, mention @dosu.
Issue Summary
When creating a managed event type via api , the even type data has inconsistency with the one created from web platform. Also its not possible to create a managed event type for team members , while following steps from cal com api reference
Steps to Reproduce
1.Create a managed event type from postman api example cal
Actual Results
Expected Results
Evidence
Loom Video : View
CAL-3915