Add Sheets-first mirror mode

This commit is contained in:
MOHAN 2026-07-17 23:41:37 +05:30
parent 25a1981909
commit 5448dbb7eb
4 changed files with 48 additions and 2 deletions

View File

@ -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';

View File

@ -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?

View File

@ -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);
}
} }

View File

@ -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",
}; };
} }
} }