feat: product design surveys, cart expiry/buy-later, and catalog polish
Add like/dislike surveys with majority alerts for manufacturing decisions, clearer accounting mapping copy, and related cart/catalog admin-app improvements. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { AccountingHttpError, httpRequest, parseLooseJson } from '../accounting-http';
|
||||
import { accountingDebug, accountingDebugEnabled } from '../accounting-debug-log';
|
||||
import { JalaliDate, jalaliToGregorian, jalaliToIsoDate, toIsoDateTehran, toJalali } from '../jalali';
|
||||
|
||||
const jalaliKey = (d: JalaliDate) => d.jy * 10000 + d.jm * 100 + d.jd;
|
||||
@@ -80,6 +81,14 @@ function isMissingKind(err: unknown) {
|
||||
return err instanceof ZarrinHttpError && err.status === 400;
|
||||
}
|
||||
|
||||
function scrubToken(text: string, token: string) {
|
||||
if (token) for (const t of new Set([token, encodeURIComponent(token)])) text = text.split(t).join('***');
|
||||
return text;
|
||||
}
|
||||
|
||||
/** Polled every few seconds; traced only when they fail. */
|
||||
const QUIET_KINDS = new Set(['parLastTenRadif', 'listMandeHesabha', 'listhesabha', 'listKarSakhte', 'mojoodiKala', 'version', 'listGorooheHesabha', 'parvande']);
|
||||
|
||||
/**
|
||||
* What the server said on a non-2xx reply, short enough for the admin screen.
|
||||
* Error pages may echo the request URL, so the token is scrubbed.
|
||||
@@ -94,8 +103,7 @@ function errorBodyText(body: string, token: string) {
|
||||
} catch {
|
||||
text = body.replace(/<(script|style)[\s\S]*?<\/\1>/gi, ' ').replace(/<[^>]+>/g, ' ');
|
||||
}
|
||||
if (token) for (const t of new Set([token, encodeURIComponent(token)])) text = text.split(t).join('***');
|
||||
text = text.replace(/\s+/g, ' ').trim();
|
||||
text = scrubToken(text, token).replace(/\s+/g, ' ').trim();
|
||||
return text.length > 200 ? `${text.slice(0, 200)}…` : text;
|
||||
}
|
||||
|
||||
@@ -133,15 +141,28 @@ async function call(
|
||||
if (v !== null && v !== undefined && v !== '') url.searchParams.set(k, String(v));
|
||||
}
|
||||
|
||||
const started = Date.now();
|
||||
const trace = (extra: Record<string, unknown>) => {
|
||||
if (!accountingDebugEnabled()) return;
|
||||
if (QUIET_KINDS.has(kind) && !extra.error) return;
|
||||
accountingDebug('zarrin.call', { kind, params, ms: Date.now() - started, ...extra });
|
||||
};
|
||||
|
||||
let res;
|
||||
try {
|
||||
res = await httpRequest({ method: 'GET', url: url.toString(), timeoutMs: opts.timeoutMs ?? s.timeoutMs, ca: s.caCert });
|
||||
} catch (err) {
|
||||
trace({ error: (err as Error).message, code: (err as AccountingHttpError).code });
|
||||
if (err instanceof AccountingHttpError) {
|
||||
throw new AccountingProviderError(`زرین (${kind}): ${err.message}`, err.ambiguous);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
trace({
|
||||
status: res.status,
|
||||
body: scrubToken(res.body, s.token).slice(0, 2000),
|
||||
...(res.status < 200 || res.status >= 300 ? { error: `HTTP ${res.status}` } : {}),
|
||||
});
|
||||
|
||||
if (res.status < 200 || res.status >= 300) {
|
||||
// v228 answers goroohSakhte with HTTP 400 and a perfectly good body.
|
||||
|
||||
Reference in New Issue
Block a user