fix(push): 일괄 판매기간 적용도 알림 발송 + 알림 아이콘 모모 로고/단색 배지
Deploy momo-erp / deploy (push) Successful in 1m56s
Deploy momo-erp / deploy (push) Successful in 1m56s
- bulk-sale-range: 리스트에서 판매기간 일괄 적용 시에도 일반 사용자 푸시. 1건이면 품목명, 여러 건이면 'N개 품목 판매' 요약. 해제(clear)는 알림 제외. - 알림 아이콘: 큰 아이콘은 모모 로고(icon-192), 상태바 작은 배지는 흰 M 단색 투명 PNG(badge-96) — 기존엔 컬러 PNG라 크롬이 지구본 기본 배지로 대체했음. - sw.js: CACHE v2 로 올려 갱신 강제 + badge-96 precache, push 핸들러가 payload icon/badge 우선 사용.
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 1014 B |
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
// 모모유통 ERP — Service Worker (PWA install criteria 충족용)
|
// 모모유통 ERP — Service Worker (PWA install criteria 충족용)
|
||||||
const CACHE = 'momo-erp-v1';
|
const CACHE = 'momo-erp-v2';
|
||||||
const PRECACHE = ['/', '/manifest.json', '/icon-192.png', '/icon-512.png'];
|
const PRECACHE = ['/', '/manifest.json', '/icon-192.png', '/icon-512.png', '/badge-96.png'];
|
||||||
|
|
||||||
self.addEventListener('install', (e) => {
|
self.addEventListener('install', (e) => {
|
||||||
e.waitUntil(caches.open(CACHE).then((c) => c.addAll(PRECACHE)).catch(() => {}));
|
e.waitUntil(caches.open(CACHE).then((c) => c.addAll(PRECACHE)).catch(() => {}));
|
||||||
@@ -33,8 +33,8 @@ self.addEventListener('push', (e) => {
|
|||||||
const title = data.title || '모모유통';
|
const title = data.title || '모모유통';
|
||||||
const options = {
|
const options = {
|
||||||
body: data.body || '',
|
body: data.body || '',
|
||||||
icon: '/icon-192.png',
|
icon: data.icon || '/icon-192.png', // 큰 아이콘 = 모모 로고(초록 M)
|
||||||
badge: '/icon-192.png',
|
badge: data.badge || '/badge-96.png', // 상태바 작은 아이콘 = 흰 M 단색(투명 배경)
|
||||||
tag: data.tag || undefined,
|
tag: data.tag || undefined,
|
||||||
data: { url: data.url || '/m/orders/new' },
|
data: { url: data.url || '/m/orders/new' },
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { pool } from "@/lib/db";
|
import { pool } from "@/lib/db";
|
||||||
import { requireMomoAdmin } from "@/lib/momo-guard";
|
import { requireMomoAdmin } from "@/lib/momo-guard";
|
||||||
|
import { sendPush } from "@/lib/push";
|
||||||
|
|
||||||
export async function POST(req: NextRequest) {
|
export async function POST(req: NextRequest) {
|
||||||
const g = await requireMomoAdmin();
|
const g = await requireMomoAdmin();
|
||||||
@@ -28,5 +29,49 @@ export async function POST(req: NextRequest) {
|
|||||||
WHERE objid IN (${placeholders})`,
|
WHERE objid IN (${placeholders})`,
|
||||||
[...objids, start, end, userId]
|
[...objids, start, end, userId]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 일괄 적용한 판매 일정이 유효(오늘/미래)한 품목이 있으면 일반 사용자에게 알림.
|
||||||
|
// 판매기간 해제(clear)는 알림 대상 아님. (상세 수정과 동일 정책)
|
||||||
|
if (!clear) {
|
||||||
|
try {
|
||||||
|
const sell = await pool.query<{ item_name: string; start_txt: string | null; orderable_now: boolean }>(
|
||||||
|
`SELECT item_name,
|
||||||
|
TO_CHAR(sale_start_date,'YYYY-MM-DD HH24:MI') AS start_txt,
|
||||||
|
(sale_start_date IS NULL OR (NOW() AT TIME ZONE 'Asia/Seoul') >= sale_start_date) AS orderable_now
|
||||||
|
FROM momo_items
|
||||||
|
WHERE objid IN (${placeholders})
|
||||||
|
AND COALESCE(is_del,'N') != 'Y'
|
||||||
|
AND UPPER(COALESCE(status,'')) = 'ACTIVE'
|
||||||
|
AND COALESCE(is_hidden,'N') != 'Y'
|
||||||
|
AND (sale_start_date IS NOT NULL OR sale_end_date IS NOT NULL)
|
||||||
|
AND (
|
||||||
|
sale_end_date IS NULL
|
||||||
|
OR (NOW() AT TIME ZONE 'Asia/Seoul') <= CASE
|
||||||
|
WHEN sale_end_date = date_trunc('day', sale_end_date)
|
||||||
|
THEN sale_end_date + INTERVAL '1 day' - INTERVAL '1 second'
|
||||||
|
ELSE sale_end_date
|
||||||
|
END
|
||||||
|
)`,
|
||||||
|
objids
|
||||||
|
);
|
||||||
|
const rows = sell.rows;
|
||||||
|
if (rows.length === 1) {
|
||||||
|
const r = rows[0];
|
||||||
|
const body = r.orderable_now
|
||||||
|
? `${r.item_name} — 지금 출고요청할 수 있어요.`
|
||||||
|
: `${r.item_name} — ${r.start_txt ?? "곧"} 판매 예정입니다.`;
|
||||||
|
await sendPush({ title: "판매 품목 안내", body, url: "/m/orders/new", tag: "item-bulk" }, undefined, { generalOnly: true });
|
||||||
|
} else if (rows.length > 1) {
|
||||||
|
await sendPush(
|
||||||
|
{ title: "판매 품목 안내", body: `${rows.length}개 품목 판매가 시작/예정되었어요. 지금 확인해보세요.`, url: "/m/orders/new", tag: "item-bulk" },
|
||||||
|
undefined,
|
||||||
|
{ generalOnly: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[bulk-sale-range notify]", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NextResponse.json({ success: true, count: res.rowCount ?? 0 });
|
return NextResponse.json({ success: true, count: res.rowCount ?? 0 });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user