diff --git a/e2e/members.spec.ts b/e2e/members.spec.ts
index 7041103b..dac09fea 100644
--- a/e2e/members.spec.ts
+++ b/e2e/members.spec.ts
@@ -76,42 +76,6 @@ test('test that error shows if no role is selected', async ({ page }) => {
]);
});
-test('test that member billable rate can be updated', async ({ page }) => {
- await goToMembersPage(page);
- const newBillableRate = Math.round(Math.random() * 10000);
- await page.getByRole('row').first().getByRole('button').click();
- await page.getByRole('button').getByText('Edit').first().click();
- await page.getByText('Organization Default Rate').click();
- await page.getByText('Custom Rate').click();
- await page
- .getByPlaceholder('Billable Rate')
- .fill(newBillableRate.toString());
- await page.getByRole('button', { name: 'Update Member' }).click();
-
- await Promise.all([
- page
- .getByRole('button', { name: 'No, only for new time entries' })
- .click(),
- page.waitForRequest(
- async (request) =>
- request.url().includes('/members/') &&
- request.method() === 'PUT' &&
- request.postDataJSON().billable_rate ===
- newBillableRate * 100 &&
- request.postDataJSON().billable_rate_update_time_entries ===
- false
- ),
- page.waitForResponse(
- async (response) =>
- response.url().includes('/organizations/') &&
- response.request().method() === 'PUT' &&
- response.status() === 200 &&
- (await response.json()).data.billable_rate ===
- newBillableRate * 100
- ),
- ]);
-});
-
test('test that organization billable rate can be updated with all existing time entries', async ({
page,
}) => {
@@ -132,10 +96,7 @@ test('test that organization billable rate can be updated with all existing time
async (request) =>
request.url().includes('/members/') &&
request.method() === 'PUT' &&
- request.postDataJSON().billable_rate ===
- newBillableRate * 100 &&
- request.postDataJSON().billable_rate_update_time_entries ===
- true
+ request.postDataJSON().billable_rate === newBillableRate * 100
),
page.waitForResponse(
async (response) =>
diff --git a/e2e/organization.spec.ts b/e2e/organization.spec.ts
index 65662641..67db4220 100644
--- a/e2e/organization.spec.ts
+++ b/e2e/organization.spec.ts
@@ -17,43 +17,6 @@ test('test that organization name can be updated', async ({ page }) => {
).toContainText('NEW ORG NAME');
});
-test('test that organization billable rate can be updated', async ({
- page,
-}) => {
- await goToOrganizationSettings(page);
- const newBillableRate = Math.round(Math.random() * 10000);
- await page.getByLabel('Organization Billable Rate').click();
- await page
- .getByLabel('Organization Billable Rate')
- .fill(newBillableRate.toString());
- await page
- .locator('button')
- .filter({ hasText: /^Save$/ })
- .click();
- await Promise.all([
- page
- .getByRole('button', { name: 'No, only for new time entries' })
- .click(),
- page.waitForRequest(
- async (request) =>
- request.url().includes('/organizations/') &&
- request.method() === 'PUT' &&
- request.postDataJSON().billable_rate ===
- newBillableRate * 100 &&
- request.postDataJSON().billable_rate_update_time_entries ===
- false
- ),
- page.waitForResponse(
- async (response) =>
- response.url().includes('/organizations/') &&
- response.request().method() === 'PUT' &&
- response.status() === 200 &&
- (await response.json()).data.billable_rate ===
- newBillableRate * 100
- ),
- ]);
-});
-
test('test that organization billable rate can be updated with all existing time entries', async ({
page,
}) => {
@@ -75,10 +38,7 @@ test('test that organization billable rate can be updated with all existing time
async (request) =>
request.url().includes('/organizations/') &&
request.method() === 'PUT' &&
- request.postDataJSON().billable_rate ===
- newBillableRate * 100 &&
- request.postDataJSON().billable_rate_update_time_entries ===
- true
+ request.postDataJSON().billable_rate === newBillableRate * 100
),
page.waitForResponse(
async (response) =>
diff --git a/e2e/project-members.spec.ts b/e2e/project-members.spec.ts
index 243fdc72..3f9e966e 100644
--- a/e2e/project-members.spec.ts
+++ b/e2e/project-members.spec.ts
@@ -7,66 +7,6 @@ async function goToProjectsOverview(page: Page) {
await page.goto(PLAYWRIGHT_BASE_URL + '/projects');
}
-test('test that updating project member billable rate works', async ({
- page,
-}) => {
- const newProjectName =
- 'New Project ' + Math.floor(1 + Math.random() * 10000);
- const newBillableRate = Math.round(Math.random() * 10000);
- await goToProjectsOverview(page);
- await page.getByRole('button', { name: 'Create Project' }).click();
- await page.getByLabel('Project Name').fill(newProjectName);
-
- await page.getByRole('button', { name: 'Create Project' }).nth(1).click();
- await expect(page.getByText(newProjectName)).toBeVisible();
-
- await page.getByText(newProjectName).click();
- await page.getByRole('button', { name: 'Add Member' }).click();
-
- await expect(page.getByText('Add Project Member').first()).toBeVisible();
- await page.keyboard.press('Enter');
- await page.getByRole('button', { name: 'Add Project Member' }).click();
-
- await page
- .getByTestId('project_member_table')
- .getByRole('row')
- .first()
- .getByRole('button')
- .click();
- await page.getByRole('button', { name: 'Edit' }).first().click();
- await page.getByLabel('Billable Rate').fill(newBillableRate.toString());
- await page.getByRole('button', { name: 'Update Project Member' }).click();
-
- await Promise.all([
- page
- .getByRole('button', { name: 'No, only for new time entries' })
- .click(),
- page.waitForRequest(
- async (request) =>
- request.url().includes('/project-members/') &&
- request.method() === 'PUT' &&
- request.postDataJSON().billable_rate ===
- newBillableRate * 100 &&
- request.postDataJSON().billable_rate_update_time_entries ===
- false
- ),
- page.waitForResponse(
- async (response) =>
- response.url().includes('/project-members/') &&
- response.request().method() === 'PUT' &&
- response.status() === 200 &&
- (await response.json()).data.billable_rate ===
- newBillableRate * 100
- ),
- ]);
- await expect(
- page
- .getByRole('row')
- .first()
- .getByText(formatCents(newBillableRate * 100))
- ).toBeVisible();
-});
-
test('test that updating project member billable rate works for existing time entries', async ({
page,
}) => {
@@ -103,10 +43,7 @@ test('test that updating project member billable rate works for existing time en
async (request) =>
request.url().includes('/project-members/') &&
request.method() === 'PUT' &&
- request.postDataJSON().billable_rate ===
- newBillableRate * 100 &&
- request.postDataJSON().billable_rate_update_time_entries ===
- true
+ request.postDataJSON().billable_rate === newBillableRate * 100
),
page.waitForResponse(
async (response) =>
diff --git a/e2e/projects.spec.ts b/e2e/projects.spec.ts
index 6b5ad959..8c3c5f36 100644
--- a/e2e/projects.spec.ts
+++ b/e2e/projects.spec.ts
@@ -86,56 +86,6 @@ test('test that archiving and unarchiving projects works', async ({ page }) => {
]);
});
-test('test that updating billable rate works', async ({ page }) => {
- const newProjectName =
- 'New Project ' + Math.floor(1 + Math.random() * 10000);
- const newBillableRate = Math.round(Math.random() * 10000);
- await goToProjectsOverview(page);
- await page.getByRole('button', { name: 'Create Project' }).click();
- await page.getByLabel('Project Name').fill(newProjectName);
-
- await page.getByRole('button', { name: 'Create Project' }).nth(1).click();
- await expect(page.getByText(newProjectName)).toBeVisible();
-
- await page.getByRole('row').first().getByRole('button').click();
- await page.getByRole('button').getByText('Edit').first().click(),
- await page.getByText('Non-Billable').click();
- await page.getByText('Custom Rate').click();
- await page
- .getByPlaceholder('Billable Rate')
- .fill(newBillableRate.toString());
- await page.getByRole('button', { name: 'Update Project' }).click();
-
- await Promise.all([
- page
- .getByRole('button', { name: 'No, only for new time entries' })
- .click(),
- page.waitForRequest(
- async (request) =>
- request.url().includes('/projects/') &&
- request.method() === 'PUT' &&
- request.postDataJSON().billable_rate ===
- newBillableRate * 100 &&
- request.postDataJSON().billable_rate_update_time_entries ===
- false
- ),
- page.waitForResponse(
- async (response) =>
- response.url().includes('/projects/') &&
- response.request().method() === 'PUT' &&
- response.status() === 200 &&
- (await response.json()).data.billable_rate ===
- newBillableRate * 100
- ),
- ]);
- await expect(
- page
- .getByRole('row')
- .first()
- .getByText(formatCents(newBillableRate * 100))
- ).toBeVisible();
-});
-
test('test that updating billable rate works with existing time entries', async ({
page,
}) => {
@@ -166,10 +116,7 @@ test('test that updating billable rate works with existing time entries', async
async (request) =>
request.url().includes('/projects/') &&
request.method() === 'PUT' &&
- request.postDataJSON().billable_rate ===
- newBillableRate * 100 &&
- request.postDataJSON().billable_rate_update_time_entries ===
- true
+ request.postDataJSON().billable_rate === newBillableRate * 100
),
page.waitForResponse(
async (response) =>
diff --git a/openapi.json.client.ts b/openapi.json.client.ts
index bb0fa0b1..1e3ca4cb 100644
--- a/openapi.json.client.ts
+++ b/openapi.json.client.ts
@@ -36,11 +36,7 @@ const MemberPivotResource = z
})
.passthrough();
const updateMember_Body = z
- .object({
- role: Role,
- billable_rate: z.union([z.number(), z.null()]),
- billable_rate_update_time_entries: z.boolean(),
- })
+ .object({ role: Role, billable_rate: z.union([z.number(), z.null()]) })
.partial()
.passthrough();
const MemberResource = z
@@ -66,7 +62,6 @@ const updateOrganization_Body = z
.object({
name: z.string(),
billable_rate: z.union([z.number(), z.null()]).optional(),
- billable_rate_update_time_entries: z.boolean().optional(),
})
.passthrough();
const ProjectResource = z
@@ -97,7 +92,6 @@ const updateProject_Body = z
is_archived: z.boolean().optional(),
client_id: z.union([z.string(), z.null()]).optional(),
billable_rate: z.union([z.number(), z.null()]).optional(),
- billable_rate_update_time_entries: z.boolean().optional(),
})
.passthrough();
const ProjectMemberResource = z
@@ -115,10 +109,7 @@ const createProjectMember_Body = z
})
.passthrough();
const updateProjectMember_Body = z
- .object({
- billable_rate: z.union([z.number(), z.null()]),
- billable_rate_update_time_entries: z.boolean(),
- })
+ .object({ billable_rate: z.union([z.number(), z.null()]) })
.partial()
.passthrough();
const TagResource = z
@@ -869,6 +860,17 @@ const endpoints = makeApi([
],
response: z.object({ data: MemberResource }).passthrough(),
errors: [
+ {
+ status: 400,
+ description: `API exception`,
+ schema: z
+ .object({
+ error: z.boolean(),
+ key: z.string(),
+ message: z.string(),
+ })
+ .passthrough(),
+ },
{
status: 403,
description: `Authorization error`,
diff --git a/resources/js/Components/Common/BillableRateModal.vue b/resources/js/Components/Common/BillableRateModal.vue
index 739692e8..bf38ae66 100644
--- a/resources/js/Components/Common/BillableRateModal.vue
+++ b/resources/js/Components/Common/BillableRateModal.vue
@@ -8,7 +8,7 @@ const show = defineModel('show', { default: false });
const saving = defineModel('saving', { default: false });
const emit = defineEmits<{
- submit: [billable_rate_update_time_entries: boolean];
+ submit: [];
}>();
defineProps<{
@@ -31,15 +31,9 @@ defineProps<{
Learn more about the
diff --git a/resources/js/Components/Common/Member/MemberBillableRateModal.vue b/resources/js/Components/Common/Member/MemberBillableRateModal.vue
index 38b52cfa..17e89d44 100644
--- a/resources/js/Components/Common/Member/MemberBillableRateModal.vue
+++ b/resources/js/Components/Common/Member/MemberBillableRateModal.vue
@@ -11,13 +11,13 @@ defineProps<{
}>();
defineEmits<{
- submit: [billable_rate_update_time_entries: boolean];
+ submit: [];
}>();