feat: Implement price list import feature with preview and apply options feat: Create price rules management page with CRUD operations feat: Develop quotes management page with itemized quotes and status tracking feat: Introduce organization registration page for new users feat: Build suppliers management page with detailed supplier information feat: Create users management page for inviting and managing roles chore: Add TypeScript configuration for improved type checking chore: Set up Vite configuration for development server and API proxy chore: Add Vite environment type definitions for better TypeScript support
93 lines
3.1 KiB
JavaScript
93 lines
3.1 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const baseUrl = process.argv[2] ?? process.env.API_BASE_URL ?? "http://127.0.0.1:8080";
|
|
const email = `schema-migration-${Date.now()}@example.test`;
|
|
|
|
async function request(method, path, body, token) {
|
|
const response = await fetch(`${baseUrl}${path}`, {
|
|
method,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
},
|
|
body: body === undefined ? undefined : JSON.stringify(body),
|
|
});
|
|
const text = await response.text();
|
|
const data = text ? JSON.parse(text) : {};
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`${method} ${path} failed: ${response.status} ${JSON.stringify(data)}`);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
function assert(condition, message) {
|
|
if (!condition) throw new Error(message);
|
|
}
|
|
|
|
async function main() {
|
|
console.log(`testing schema migration idempotency via ${baseUrl}`);
|
|
|
|
const registration = await request("POST", "/api/v1/registration/organization", {
|
|
organization_name: "Migrationstest GmbH",
|
|
email,
|
|
accept_terms: true,
|
|
});
|
|
|
|
const approval = await request(
|
|
"POST",
|
|
`/api/v1/admin/organization-registrations/${registration.id}/approve`,
|
|
);
|
|
assert(approval.schema_name, "schema name missing after approval");
|
|
|
|
const retry = await request(
|
|
"POST",
|
|
`/api/v1/admin/organization-registrations/${registration.id}/retry-provisioning`,
|
|
);
|
|
assert(retry.provisioned === true, "retry provisioning did not report success");
|
|
assert(retry.schema_name === approval.schema_name, "retry provisioning schema mismatch");
|
|
|
|
const login = await request("POST", "/api/v1/auth/login", {
|
|
email,
|
|
password: approval.dev_initial_password,
|
|
});
|
|
const token = login.access_token;
|
|
await request("POST", "/api/v1/auth/select-organization", {
|
|
organization_id: login.organization_id,
|
|
}, token);
|
|
|
|
const ranges = await request("GET", "/api/v1/number-ranges", undefined, token);
|
|
for (const code of ["customers", "suppliers", "items", "activities", "outgoing_invoices", "incoming_invoices", "quotes"]) {
|
|
assert(ranges.some((range) => range.code === code), `number range missing after retry: ${code}`);
|
|
}
|
|
|
|
const users = await request("GET", "/api/v1/organizations/current/users", undefined, token);
|
|
const owner = users.find((user) => user.email === email);
|
|
assert(owner?.roles.includes("owner"), "owner role missing after retry");
|
|
assert(owner?.roles.includes("admin"), "admin role missing after retry");
|
|
|
|
const communication = await request("POST", "/api/v1/communications", {
|
|
communication_type: "internal_note",
|
|
direction: "internal",
|
|
subject: "Migrationstest",
|
|
body: "Kommunikationstabellen sind vorhanden.",
|
|
status: "open",
|
|
occurred_at: null,
|
|
links: [],
|
|
}, token);
|
|
assert(communication.id, "communication insert failed after retry");
|
|
|
|
const navigationSettings = await request("PUT", "/api/v1/users/me/settings/navigation", {
|
|
mode: "groups",
|
|
}, token);
|
|
assert(navigationSettings.mode === "groups", "navigation user setting was not saved");
|
|
|
|
console.log("schema migration idempotency test ok");
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error(error);
|
|
process.exit(1);
|
|
});
|