@zhin.js/plugin-ledger 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/commands/ledger-add/index.js +6 -4
- package/commands/ledger-add/index.ts +6 -4
- package/commands/ledger-delete/index.js +6 -4
- package/commands/ledger-delete/index.ts +6 -4
- package/commands/ledger-list/index.js +8 -6
- package/commands/ledger-list/index.ts +8 -6
- package/commands/ledger-month/index.js +5 -3
- package/commands/ledger-month/index.ts +5 -3
- package/commands/ledger-report/index.js +11 -11
- package/commands/ledger-report/index.ts +10 -12
- package/commands/ledger-stats/index.js +8 -6
- package/commands/ledger-stats/index.ts +8 -6
- package/commands/ledger-today/index.js +5 -3
- package/commands/ledger-today/index.ts +5 -3
- package/commands/ledger-week/index.js +5 -3
- package/commands/ledger-week/index.ts +5 -3
- package/lib/config.js +3 -3
- package/lib/config.js.map +1 -1
- package/lib/entry-input.d.ts +3 -2
- package/lib/entry-input.d.ts.map +1 -1
- package/lib/entry-input.js +11 -9
- package/lib/entry-input.js.map +1 -1
- package/lib/i18n.d.ts +2 -0
- package/lib/i18n.d.ts.map +1 -0
- package/lib/i18n.js +200 -0
- package/lib/i18n.js.map +1 -0
- package/lib/identity.d.ts +3 -1
- package/lib/identity.d.ts.map +1 -1
- package/lib/identity.js +5 -2
- package/lib/identity.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/money.d.ts +2 -1
- package/lib/money.d.ts.map +1 -1
- package/lib/money.js +6 -5
- package/lib/money.js.map +1 -1
- package/lib/period.d.ts +4 -3
- package/lib/period.d.ts.map +1 -1
- package/lib/period.js +8 -16
- package/lib/period.js.map +1 -1
- package/lib/report-format.d.ts +5 -4
- package/lib/report-format.d.ts.map +1 -1
- package/lib/report-format.js +25 -24
- package/lib/report-format.js.map +1 -1
- package/lib/service.d.ts +1 -1
- package/lib/service.d.ts.map +1 -1
- package/lib/service.js +59 -25
- package/lib/service.js.map +1 -1
- package/lib/store.d.ts +9 -1
- package/lib/store.d.ts.map +1 -1
- package/lib/store.js +32 -3
- package/lib/store.js.map +1 -1
- package/package.json +7 -7
- package/schema.json +15 -0
- package/src/config.ts +3 -3
- package/src/entry-input.ts +12 -9
- package/src/i18n.ts +200 -0
- package/src/identity.ts +6 -2
- package/src/index.ts +1 -1
- package/src/money.ts +7 -5
- package/src/period.ts +7 -13
- package/src/report-format.ts +26 -24
- package/src/service.ts +59 -26
- package/src/store.ts +33 -3
package/src/store.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { resolveLocale, type Locale } from 'zhin.js/i18n';
|
|
1
2
|
import type { DatabaseHostModel, DeliveryTarget, PluginDatabaseHost } from 'zhin.js';
|
|
2
3
|
|
|
3
4
|
export const ENTRY_TABLE = 'ledger_entries';
|
|
4
5
|
export const USER_TABLE = 'ledger_users';
|
|
6
|
+
/** Separate table: existing databases only run CREATE TABLE IF NOT EXISTS, so new columns on `ledger_users` would never appear. */
|
|
7
|
+
export const PRIVATE_TARGET_TABLE = 'ledger_private_targets';
|
|
5
8
|
|
|
6
9
|
/** One expense. `seq` is the per-user number shown as `#id`; amounts are integer cents. */
|
|
7
10
|
export interface LedgerEntry {
|
|
@@ -18,6 +21,7 @@ export interface LedgerUserRecord {
|
|
|
18
21
|
readonly ownerKey: string;
|
|
19
22
|
readonly nextSeq: number;
|
|
20
23
|
readonly reportEnabled: boolean;
|
|
24
|
+
readonly reportLocale?: Locale;
|
|
21
25
|
readonly reportTarget: DeliveryTarget | undefined;
|
|
22
26
|
readonly lastReportDate: string;
|
|
23
27
|
}
|
|
@@ -36,8 +40,13 @@ export function defineLedgerTables(database: Pick<PluginDatabaseHost, 'define'>)
|
|
|
36
40
|
owner_key: { type: 'text', nullable: false },
|
|
37
41
|
next_seq: { type: 'integer', default: 1 },
|
|
38
42
|
report_enabled: { type: 'integer', default: 0 },
|
|
43
|
+
report_locale: { type: 'text', length: 16, nullable: true },
|
|
39
44
|
report_target: { type: 'text', default: '' },
|
|
40
45
|
last_report_date: { type: 'text', default: '' },
|
|
46
|
+
}, { addColumns: ['report_locale'] });
|
|
47
|
+
database.define(PRIVATE_TARGET_TABLE, {
|
|
48
|
+
owner_key: { type: 'text', nullable: false },
|
|
49
|
+
target: { type: 'text', nullable: false },
|
|
41
50
|
});
|
|
42
51
|
}
|
|
43
52
|
|
|
@@ -66,6 +75,7 @@ function toUser(row: Record<string, unknown>): LedgerUserRecord {
|
|
|
66
75
|
ownerKey: String(row.owner_key),
|
|
67
76
|
nextSeq: Number(row.next_seq ?? 1),
|
|
68
77
|
reportEnabled: Number(row.report_enabled ?? 0) === 1,
|
|
78
|
+
reportLocale: resolveLocale(row.report_locale),
|
|
69
79
|
reportTarget: parseTarget(row.report_target),
|
|
70
80
|
lastReportDate: String(row.last_report_date ?? ''),
|
|
71
81
|
};
|
|
@@ -91,7 +101,7 @@ export class LedgerStore {
|
|
|
91
101
|
|
|
92
102
|
async getUser(ownerKey: string): Promise<LedgerUserRecord | undefined> {
|
|
93
103
|
const rows = await this.#model(USER_TABLE)
|
|
94
|
-
.select('owner_key', 'next_seq', 'report_enabled', 'report_target', 'last_report_date')
|
|
104
|
+
.select('owner_key', 'next_seq', 'report_enabled', 'report_locale', 'report_target', 'last_report_date')
|
|
95
105
|
.where({ owner_key: ownerKey });
|
|
96
106
|
const first = rows[0];
|
|
97
107
|
return first ? toUser(first) : undefined;
|
|
@@ -148,18 +158,38 @@ export class LedgerStore {
|
|
|
148
158
|
await this.#model(ENTRY_TABLE).delete().where({ owner_key: ownerKey, seq });
|
|
149
159
|
}
|
|
150
160
|
|
|
151
|
-
async setReport(ownerKey: string, enabled: boolean, target: DeliveryTarget | undefined, lastReportDate: string): Promise<void> {
|
|
161
|
+
async setReport(ownerKey: string, enabled: boolean, target: DeliveryTarget | undefined, lastReportDate: string, locale?: Locale): Promise<void> {
|
|
152
162
|
await this.#ensureUser(ownerKey);
|
|
153
163
|
await this.#model(USER_TABLE).update({
|
|
154
164
|
report_enabled: enabled ? 1 : 0,
|
|
165
|
+
...(enabled ? { report_locale: resolveLocale(locale) } : {}),
|
|
155
166
|
report_target: target ? JSON.stringify(target) : '',
|
|
156
167
|
last_report_date: lastReportDate,
|
|
157
168
|
}).where({ owner_key: ownerKey });
|
|
158
169
|
}
|
|
159
170
|
|
|
171
|
+
/** The real private conversation saved when the user talked to the bot in private. */
|
|
172
|
+
async getPrivateTarget(ownerKey: string): Promise<DeliveryTarget | undefined> {
|
|
173
|
+
const rows = await this.#model(PRIVATE_TARGET_TABLE).select('owner_key', 'target').where({ owner_key: ownerKey });
|
|
174
|
+
return parseTarget(rows[0]?.target);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Saves the real private conversation; an enabled daily report follows it. */
|
|
178
|
+
async setPrivateTarget(ownerKey: string, target: DeliveryTarget): Promise<void> {
|
|
179
|
+
const raw = JSON.stringify(target);
|
|
180
|
+
const model = this.#model(PRIVATE_TARGET_TABLE);
|
|
181
|
+
const existing = await model.select('owner_key', 'target').where({ owner_key: ownerKey });
|
|
182
|
+
if (existing.length > 0) await model.update({ target: raw }).where({ owner_key: ownerKey });
|
|
183
|
+
else await model.insert({ owner_key: ownerKey, target: raw });
|
|
184
|
+
const user = await this.getUser(ownerKey);
|
|
185
|
+
if (user?.reportEnabled) {
|
|
186
|
+
await this.#model(USER_TABLE).update({ report_target: raw }).where({ owner_key: ownerKey });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
160
190
|
async listReportSubscribers(): Promise<LedgerUserRecord[]> {
|
|
161
191
|
const rows = await this.#model(USER_TABLE)
|
|
162
|
-
.select('owner_key', 'next_seq', 'report_enabled', 'report_target', 'last_report_date')
|
|
192
|
+
.select('owner_key', 'next_seq', 'report_enabled', 'report_locale', 'report_target', 'last_report_date')
|
|
163
193
|
.where({ report_enabled: 1 });
|
|
164
194
|
return rows.map(toUser);
|
|
165
195
|
}
|