Add Sheets-first mirror mode
This commit is contained in:
parent
25a1981909
commit
5448dbb7eb
@ -0,0 +1,2 @@
|
|||||||
|
-- Track user-selected data ownership/system-of-record posture.
|
||||||
|
ALTER TABLE "GoogleConnection" ADD COLUMN "dataSystemMode" TEXT NOT NULL DEFAULT 'backend_db';
|
||||||
@ -664,6 +664,7 @@ model GoogleConnection {
|
|||||||
driveMirrorStatus String @default("not_started")
|
driveMirrorStatus String @default("not_started")
|
||||||
driveMirrorSpreadsheetUrl String?
|
driveMirrorSpreadsheetUrl String?
|
||||||
driveMirrorLastSyncedAt DateTime?
|
driveMirrorLastSyncedAt DateTime?
|
||||||
|
dataSystemMode String @default("backend_db")
|
||||||
isConnected Boolean @default(true)
|
isConnected Boolean @default(true)
|
||||||
connectedAt DateTime @default(now())
|
connectedAt DateTime @default(now())
|
||||||
lastSyncedAt DateTime?
|
lastSyncedAt DateTime?
|
||||||
|
|||||||
@ -30,4 +30,10 @@ export class GoogleController {
|
|||||||
status(@CurrentUser() userId: string) {
|
status(@CurrentUser() userId: string) {
|
||||||
return this.googleService.getStatus(userId);
|
return this.googleService.getStatus(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post("data-system-mode")
|
||||||
|
@HttpCode(200)
|
||||||
|
dataSystemMode(@CurrentUser() userId: string, @Body() body: { mode: "backend_db" | "google_sheets_mirror" }) {
|
||||||
|
return this.googleService.updateDataSystemMode(userId, body.mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,7 +58,7 @@ export class GoogleService {
|
|||||||
const { data } = await oauth2.userinfo.get();
|
const { data } = await oauth2.userinfo.get();
|
||||||
const googleEmail = data.email ?? "";
|
const googleEmail = data.email ?? "";
|
||||||
|
|
||||||
await this.prisma.googleConnection.upsert({
|
await (this.prisma as any).googleConnection.upsert({
|
||||||
where: { userId },
|
where: { userId },
|
||||||
update: {
|
update: {
|
||||||
googleEmail,
|
googleEmail,
|
||||||
@ -71,6 +71,7 @@ export class GoogleService {
|
|||||||
driveMirrorStatus: "pending_first_sync",
|
driveMirrorStatus: "pending_first_sync",
|
||||||
driveMirrorSpreadsheetUrl: null,
|
driveMirrorSpreadsheetUrl: null,
|
||||||
driveMirrorLastSyncedAt: null,
|
driveMirrorLastSyncedAt: null,
|
||||||
|
dataSystemMode: "backend_db",
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
userId,
|
userId,
|
||||||
@ -80,6 +81,7 @@ export class GoogleService {
|
|||||||
isConnected: true,
|
isConnected: true,
|
||||||
driveMirrorEnabled: false,
|
driveMirrorEnabled: false,
|
||||||
driveMirrorStatus: "pending_first_sync",
|
driveMirrorStatus: "pending_first_sync",
|
||||||
|
dataSystemMode: "backend_db",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -93,7 +95,7 @@ export class GoogleService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getStatus(userId: string) {
|
async getStatus(userId: string) {
|
||||||
const gc = await this.prisma.googleConnection.findUnique({ where: { userId } });
|
const gc = await (this.prisma as any).googleConnection.findUnique({ where: { userId } });
|
||||||
if (!gc || !gc.isConnected) return { connected: false };
|
if (!gc || !gc.isConnected) return { connected: false };
|
||||||
return {
|
return {
|
||||||
connected: true,
|
connected: true,
|
||||||
@ -107,6 +109,41 @@ export class GoogleService {
|
|||||||
lastSyncedAt: gc.driveMirrorLastSyncedAt ?? gc.lastSyncedAt,
|
lastSyncedAt: gc.driveMirrorLastSyncedAt ?? gc.lastSyncedAt,
|
||||||
ownership: "user_google_drive",
|
ownership: "user_google_drive",
|
||||||
},
|
},
|
||||||
|
dataSystem: {
|
||||||
|
mode: gc.dataSystemMode,
|
||||||
|
operationalSystemOfRecord: "ledgerone_backend_db",
|
||||||
|
userOwnedMirror: gc.dataSystemMode === "google_sheets_mirror",
|
||||||
|
note: gc.dataSystemMode === "google_sheets_mirror"
|
||||||
|
? "LedgerOne writes a best-effort user-owned Google Sheets mirror while the application database remains the operational store."
|
||||||
|
: "LedgerOne uses the application database as the operational store. Google Sheets can be enabled as a user-owned mirror.",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateDataSystemMode(userId: string, mode: "backend_db" | "google_sheets_mirror") {
|
||||||
|
if (!["backend_db", "google_sheets_mirror"].includes(mode)) {
|
||||||
|
throw new BadRequestException("Unsupported data system mode.");
|
||||||
|
}
|
||||||
|
const connection = await (this.prisma as any).googleConnection.findUnique({ where: { userId } });
|
||||||
|
if (!connection || !connection.isConnected) {
|
||||||
|
throw new BadRequestException("Google account must be connected before enabling Sheets-first mirror mode.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const updated = await (this.prisma as any).googleConnection.update({
|
||||||
|
where: { userId },
|
||||||
|
data: {
|
||||||
|
dataSystemMode: mode,
|
||||||
|
driveMirrorEnabled: mode === "google_sheets_mirror" ? true : connection.driveMirrorEnabled,
|
||||||
|
driveMirrorStatus: mode === "google_sheets_mirror" && !connection.spreadsheetId ? "pending_first_sync" : connection.driveMirrorStatus,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
mode: updated.dataSystemMode,
|
||||||
|
driveMirrorEnabled: updated.driveMirrorEnabled,
|
||||||
|
status: updated.driveMirrorStatus,
|
||||||
|
operationalSystemOfRecord: "ledgerone_backend_db",
|
||||||
|
userOwnedMirror: updated.dataSystemMode === "google_sheets_mirror",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user