@xuda.io/account_module 1.2.2303 → 1.2.2304
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/index.mjs +59 -0
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -1678,6 +1678,10 @@ export const get_account_data = async function (req) {
|
|
|
1678
1678
|
// one-shot notice at suspension time can be missed or predate this). Best-
|
|
1679
1679
|
// effort + fire-and-forget; only touches the DB for the rare suspended account.
|
|
1680
1680
|
if (acc_obj.account_email_bounce_suspended) _ensure_bounce_suspension_banner(acc_obj);
|
|
1681
|
+
// UI-82: same treatment for the billing hold. Called on every load, not
|
|
1682
|
+
// only when the hold is on, because this is also what retires the banner
|
|
1683
|
+
// once the hold is lifted.
|
|
1684
|
+
_ensure_billing_hold_banner(acc_obj);
|
|
1681
1685
|
|
|
1682
1686
|
return ret;
|
|
1683
1687
|
} catch (err) {
|
|
@@ -4887,6 +4891,61 @@ const _notify_bounce_suspended = async (account) => {
|
|
|
4887
4891
|
// can be missed or predate this; get_account_data calls this on every load.
|
|
4888
4892
|
// Idempotent + banner-only: bails if a persistent (app_id '') banner already
|
|
4889
4893
|
// exists, so it never duplicates the doc or re-sends the SMS.
|
|
4894
|
+
// The billing-hold band, as a notification instead of a hardcoded strip in the
|
|
4895
|
+
// dashboard shell (UI-82). Driven by account state on every load rather than
|
|
4896
|
+
// hooked onto the four places that flip the flag (ops apply, ops release, and
|
|
4897
|
+
// both Stripe webhook paths), because a state check cannot drift out of sync
|
|
4898
|
+
// with the flag the way four call sites can. Raises the banner while the hold
|
|
4899
|
+
// is on, retires it when the hold lifts.
|
|
4900
|
+
const _ensure_billing_hold_banner = async (account) => {
|
|
4901
|
+
try {
|
|
4902
|
+
const uid = account._id;
|
|
4903
|
+
const on = account.account_billing_hold_status === 1;
|
|
4904
|
+
const ret = await db_module.find_couch_query('xuda_notification', {
|
|
4905
|
+
selector: { docType: 'notification', uid, topic: 'account_billing_hold', delivery_method: 'banner', read: false },
|
|
4906
|
+
});
|
|
4907
|
+
const docs = ret?.docs || [];
|
|
4908
|
+
|
|
4909
|
+
if (!on) {
|
|
4910
|
+
// Hold lifted: retire whatever is on screen. Same read + stat 4 the
|
|
4911
|
+
// bounce banner uses for its duplicates, so the notification centre
|
|
4912
|
+
// treats it as handled rather than leaving a stale warning up.
|
|
4913
|
+
for (const doc of docs) {
|
|
4914
|
+
doc.read = true;
|
|
4915
|
+
doc.stat = 4;
|
|
4916
|
+
doc.stat_ts = Date.now();
|
|
4917
|
+
await db_module.save_couch_doc('xuda_notification', doc).catch(() => {});
|
|
4918
|
+
}
|
|
4919
|
+
return;
|
|
4920
|
+
}
|
|
4921
|
+
|
|
4922
|
+
// Same de-duplication as the bounce banner: find-then-create is not atomic
|
|
4923
|
+
// and the index lags a fresh doc, so concurrent loads can both create one.
|
|
4924
|
+
if (docs.length) {
|
|
4925
|
+
docs.sort((a, b) => (b.date_created_ts || 0) - (a.date_created_ts || 0));
|
|
4926
|
+
for (let i = 1; i < docs.length; i++) {
|
|
4927
|
+
docs[i].read = true;
|
|
4928
|
+
docs[i].stat = 4;
|
|
4929
|
+
docs[i].stat_ts = Date.now();
|
|
4930
|
+
await db_module.save_couch_doc('xuda_notification', docs[i]).catch(() => {});
|
|
4931
|
+
}
|
|
4932
|
+
return;
|
|
4933
|
+
}
|
|
4934
|
+
|
|
4935
|
+
const host = _conf.is_debug ? process.env.XUDA_HOSTNAME || _conf.domain : _conf.domain;
|
|
4936
|
+
await notification_msa.submit_notification({
|
|
4937
|
+
type: 'account',
|
|
4938
|
+
app_id: null,
|
|
4939
|
+
to_app_id: '',
|
|
4940
|
+
uid_arr: [uid],
|
|
4941
|
+
topic: 'account_billing_hold',
|
|
4942
|
+
params: { action_label: 'Review billing', action_href: `https://${host}/dashboard/settings/billing` },
|
|
4943
|
+
});
|
|
4944
|
+
} catch (e) {
|
|
4945
|
+
console.error('ensure billing hold banner failed:', e.message);
|
|
4946
|
+
}
|
|
4947
|
+
};
|
|
4948
|
+
|
|
4890
4949
|
const _ensure_bounce_suspension_banner = async (account) => {
|
|
4891
4950
|
try {
|
|
4892
4951
|
const uid = account._id;
|