diff --git a/apps/admin-panel/src/views/report/order_item.vue b/apps/admin-panel/src/views/report/order_item.vue index 8df7b42..829b088 100644 --- a/apps/admin-panel/src/views/report/order_item.vue +++ b/apps/admin-panel/src/views/report/order_item.vue @@ -14,7 +14,11 @@ - اعمال + + اعمال + + دریافت فایل اکسل + @@ -46,6 +50,7 @@ diff --git a/apps/api/package.json b/apps/api/package.json index 8dec4f2..5e7d526 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -27,6 +27,7 @@ "bcryptjs": "^3.0.3", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", + "exceljs": "^4.4.0", "passport": "^0.7.0", "passport-jwt": "^4.0.1", "reflect-metadata": "^0.2.2", diff --git a/apps/api/src/app.module.ts b/apps/api/src/app.module.ts index 1366eb3..712ee87 100644 --- a/apps/api/src/app.module.ts +++ b/apps/api/src/app.module.ts @@ -32,6 +32,7 @@ import { AdminInvoicesModule } from './modules/admin-invoices/admin-invoices.mod import { AdminMiscModule } from './modules/admin-misc/admin-misc.module'; import { AdminUploadsModule } from './modules/admin-uploads/admin-uploads.module'; import { AdminDashboardModule } from './modules/admin-dashboard/admin-dashboard.module'; +import { AdminReportModule } from './modules/admin-report/admin-report.module'; import { SalesAgentModule } from './modules/sales-agent/sales-agent.module'; @Module({ @@ -58,6 +59,7 @@ import { SalesAgentModule } from './modules/sales-agent/sales-agent.module'; AdminMiscModule, AdminUploadsModule, AdminDashboardModule, + AdminReportModule, CatalogModule, CustomersModule, SmsModule, diff --git a/apps/api/src/modules/admin-documents/admin-documents.service.ts b/apps/api/src/modules/admin-documents/admin-documents.service.ts index 2bd7911..160809f 100644 --- a/apps/api/src/modules/admin-documents/admin-documents.service.ts +++ b/apps/api/src/modules/admin-documents/admin-documents.service.ts @@ -3,6 +3,7 @@ import { LedgerCurrency, LedgerDirection, LedgerSourceType, Prisma } from '@pris import { PrismaService } from '../../prisma/prisma.service'; import { TableService } from '../admin-table/table.service'; import { LedgerService } from '../accounting/ledger.service'; +import { SmsService } from '../sms/sms.service'; import type { TableQueryDto } from '../admin-table/table-query.dto'; /** @@ -62,6 +63,7 @@ export class AdminDocumentsService { private readonly prisma: PrismaService, private readonly table: TableService, private readonly ledger: LedgerService, + private readonly sms: SmsService, ) {} private static readonly ALLOWED = [ @@ -313,6 +315,7 @@ export class AdminDocumentsService { if (!e.confirmed) { await this.ledger.confirmEntry(id, adminUserId); + this.notifyDocumentConfirm(e.customerId, true); return this.findOne(id); } @@ -335,9 +338,24 @@ export class AdminDocumentsService { }); }); + this.notifyDocumentConfirm(e.customerId, false); return this.findOne(id); } + // Legacy CashController::toggleConfiremCash sent an SMS on both outcomes. + private notifyDocumentConfirm(customerId: string, confirmed: boolean) { + const text = confirmed + ? 'هنزا گلد\nسند مالی شما توسط مدیر سیستم تایید شد.' + : 'هنزا گلد\nسند مالی شما توسط مدیر سیستم رد شد.'; + + this.prisma.customer + .findUnique({ where: { id: customerId }, select: { mobile: true } }) + .then((c) => { + if (c) this.sms.send(c.mobile, text); + }) + .catch(() => {}); + } + /** * Legacy `DELETE cash/{id}`. * diff --git a/apps/api/src/modules/admin-misc/admin-misc.cities.spec.ts b/apps/api/src/modules/admin-misc/admin-misc.cities.spec.ts index 8f28a58..5f85cde 100644 --- a/apps/api/src/modules/admin-misc/admin-misc.cities.spec.ts +++ b/apps/api/src/modules/admin-misc/admin-misc.cities.spec.ts @@ -27,7 +27,7 @@ describe('AdminMiscService — city tree', () => { update, }, }; - service = new AdminMiscService(prisma as never, {} as never); + service = new AdminMiscService(prisma as never, {} as never, {} as never); }); it('a city without its own percent takes the nearest ancestor’s (legacy _getP)', async () => { diff --git a/apps/api/src/modules/admin-misc/admin-misc.service.ts b/apps/api/src/modules/admin-misc/admin-misc.service.ts index dd185c3..d2de577 100644 --- a/apps/api/src/modules/admin-misc/admin-misc.service.ts +++ b/apps/api/src/modules/admin-misc/admin-misc.service.ts @@ -2,6 +2,7 @@ import { BadRequestException, Injectable, NotFoundException } from '@nestjs/comm import { MessageAudience, Prisma } from '@prisma/client'; import { PrismaService } from '../../prisma/prisma.service'; import { TableService } from '../admin-table/table.service'; +import { SmsService } from '../sms/sms.service'; import type { TableQueryDto } from '../admin-table/table-query.dto'; import { ACCOUNTING_SETTING_PREFIX } from '../accounting-sync/accounting-config'; import { PRICING_SETTING_PREFIX } from '../pricing/wage.service'; @@ -23,6 +24,7 @@ export class AdminMiscService { constructor( private readonly prisma: PrismaService, private readonly table: TableService, + private readonly sms: SmsService, ) {} // ── Cities ───────────────────────────────────────────────────────── @@ -245,12 +247,9 @@ export class AdminMiscService { } /** - * Legacy `POST sms` — records the send. - * - * NOTE no SMS gateway is wired up: legacy handed the message to an external - * provider, and this port has no credentials for one. The message is stored - * with the audience it resolved to, so the log is accurate, but nothing is - * actually transmitted. Flagged in docs/ADMIN-PORT-PLAN.md. + * Legacy `POST sms` — resolves the audience, substitutes `%name` per + * recipient (legacy SmsController::batch + replaceName), delivers via the + * configured gateway (D26 relay), and records the send. */ async sendSms( data: { type?: string | number; mobile?: string; text?: string }, @@ -262,6 +261,18 @@ export class AdminMiscService { const audience = this.resolveAudience(data.type); const recipients = await this.resolveRecipients(audience, data.mobile); + const needsNameSub = body.includes('%name'); + const customersByMobile = needsNameSub + ? await this.customerNamesByMobile(recipients) + : new Map(); + + for (const mobile of recipients) { + const text = needsNameSub + ? body.replace(/%name/g, customersByMobile.get(mobile) ?? 'مشتری عزیز') + : body; + this.sms.send(mobile, text, { audience }); + } + return this.prisma.smsMessage.create({ data: { audience, @@ -273,6 +284,18 @@ export class AdminMiscService { }); } + private async customerNamesByMobile(mobiles: string[]): Promise> { + const rows = await this.prisma.customer.findMany({ + where: { mobile: { in: mobiles } }, + select: { mobile: true, fullName: true }, + }); + const map = new Map(); + for (const r of rows) { + if (r.fullName) map.set(r.mobile, r.fullName + ' عزیز'); + } + return map; + } + /** * Legacy's numeric audience codes, read off views/sms/create.vue where each * option is gated by its own rid: diff --git a/apps/api/src/modules/admin-report/admin-report.controller.ts b/apps/api/src/modules/admin-report/admin-report.controller.ts new file mode 100644 index 0000000..7376b5e --- /dev/null +++ b/apps/api/src/modules/admin-report/admin-report.controller.ts @@ -0,0 +1,21 @@ +import { Controller, Get, Query } from '@nestjs/common'; +import { AdminReportService } from './admin-report.service'; +import { RequirePermission } from '../auth/guards'; + +/** + * Legacy `GET report/get-order-item-with-details` — a combined order-item + + * financial-document Excel export with 32 Persian-header columns, date-filtered. + */ +@Controller('admin/report') +export class AdminReportController { + constructor(private readonly report: AdminReportService) {} + + @Get('order-items') + @RequirePermission('report.order.item') + getOrderItemReport( + @Query('start_date') startDate?: string, + @Query('end_date') endDate?: string, + ) { + return this.report.getOrderItemReport(startDate, endDate); + } +} diff --git a/apps/api/src/modules/admin-report/admin-report.module.ts b/apps/api/src/modules/admin-report/admin-report.module.ts new file mode 100644 index 0000000..0495e86 --- /dev/null +++ b/apps/api/src/modules/admin-report/admin-report.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { PrismaModule } from '../../prisma/prisma.module'; +import { AdminReportController } from './admin-report.controller'; +import { AdminReportService } from './admin-report.service'; + +@Module({ + imports: [PrismaModule], + controllers: [AdminReportController], + providers: [AdminReportService], +}) +export class AdminReportModule {} diff --git a/apps/api/src/modules/admin-report/admin-report.service.ts b/apps/api/src/modules/admin-report/admin-report.service.ts new file mode 100644 index 0000000..c6ea7fb --- /dev/null +++ b/apps/api/src/modules/admin-report/admin-report.service.ts @@ -0,0 +1,221 @@ +import { BadRequestException, Injectable, StreamableFile } from '@nestjs/common'; +import { LedgerSourceType, Prisma } from '@prisma/client'; +import { PrismaService } from '../../prisma/prisma.service'; +import { toJalali, formatJalali } from '../accounting-sync/jalali'; +import * as ExcelJS from 'exceljs'; + +const TYPE_LABELS: Partial> = { + REPAYMENT_MELTED_GOLD: 'آب شده', + REPAYMENT_TRANSFER: 'حواله', + REPAYMENT_CHEQUE: 'چک', + REPAYMENT_CASH: 'پولی', +}; + +const REPAYMENT_TYPES: LedgerSourceType[] = [ + LedgerSourceType.REPAYMENT_MELTED_GOLD, + LedgerSourceType.REPAYMENT_TRANSFER, + LedgerSourceType.REPAYMENT_CHEQUE, + LedgerSourceType.REPAYMENT_CASH, +]; + +const HEADERS = [ + 'کد آیتم', + 'نام محصول', + 'کد محصول', + 'عنوان تنوع', + 'وزن خام تحویل مشتری', + 'وزن نهایی با درصد', + 'تعداد', + 'درصد', + 'اجرت ریالی', + 'توضیحات', + 'شماره سفارش', + 'تاریخ ثبت', + 'تاریخ', + 'سال', + 'ماه', + 'روز', + 'ساعت', + 'شماره سند', + 'نوع سند', + 'میزان پول', + 'میزان گرم', + 'وضعیت سند', + 'نام مشتری', + 'نام خانوادگی مشتری', + 'نام و نام خانوادگی مشتری', + 'کارشناس فروش', + 'شماره موبایل مشتری', + 'آدرس', + 'تلفن مغازه', + 'بدهکار', + 'بستانکار', + 'بدهی ریالی', +]; + +@Injectable() +export class AdminReportService { + constructor(private readonly prisma: PrismaService) {} + + async getOrderItemReport(startDate?: string, endDate?: string): Promise { + const dateFilter: Prisma.DateTimeFilter = {}; + if (startDate) dateFilter.gte = parseDate(startDate, 'از تاریخ'); + if (endDate) { + // The whole end day, as the on-screen report (admin-dashboard dateWhere). + const end = parseDate(endDate, 'تا تاریخ'); + end.setHours(23, 59, 59, 999); + dateFilter.lte = end; + } + const hasDateFilter = startDate || endDate; + + const orderItems = await this.prisma.orderItem.findMany({ + where: hasDateFilter ? { order: { createdAt: dateFilter } } : undefined, + orderBy: { id: 'desc' }, + include: { + order: { + include: { + customer: true, + salesAgent: true, + }, + }, + productVariant: { include: { product: true } }, + }, + }); + + const ledgerEntries = await this.prisma.ledgerEntry.findMany({ + where: { + sourceType: { in: REPAYMENT_TYPES }, + ...(hasDateFilter ? { createdAt: dateFilter } : {}), + }, + include: { customer: true }, + }); + + const wb = new ExcelJS.Workbook(); + const ws = wb.addWorksheet('گزارش', { + views: [{ rightToLeft: true }], + }); + + ws.columns = HEADERS.map((h) => ({ header: h, width: 18 })); + + for (const item of orderItems) { + const order = item.order; + const customer = order.customer; + const jalali = toJalali(order.createdAt); + const jalaliStr = formatJalali(jalali, '/'); + const hour = new Date(order.createdAt.getTime() + 3.5 * 60 * 60 * 1000) + .toISOString() + .slice(11, 16); + + // computedWeightGrams is ONE unit's weight (OrdersService.createOrder + // multiplies it by quantity for the order total), as legacy's order_items.w + // is. Legacy's export divided it by qty again, so every multi-unit line + // under-reported its weight; not repeated here. + const perUnitWeight = Number(item.computedWeightGrams); + // Legacy's «درصد» is the final percent: percent_pay − discount. + const finalPercent = Number(item.wagePercentSnapshot.sub(item.discountPercentSnapshot)); + + for (let i = 0; i < item.quantity; i++) { + ws.addRow([ + item.id, + item.productVariant?.product?.title ?? '', + item.productVariant?.product?.productCode ?? '', + item.productVariant?.title ?? '', + Number(item.rashWeightGramsSnapshot), + round4(perUnitWeight), + 1, + finalPercent, + Number(item.flatRialCharge), + '', + order.orderNumber, + jalaliStr, + jalaliStr, + jalali.jy, + jalali.jm, + jalali.jd, + hour, + null, + null, + null, + null, + null, + customer.firstName ?? '', + customer.lastName ?? '', + customer.fullName, + order.salesAgent?.fullName ?? '', + customer.mobile, + customer.address ?? '', + customer.phone ?? '', + round4(perUnitWeight), + 0, + Number(item.flatRialCharge), + ]); + } + } + + for (const entry of ledgerEntries) { + const customer = entry.customer; + const jalali = toJalali(entry.createdAt); + const jalaliStr = formatJalali(jalali, '/'); + const hour = new Date(entry.createdAt.getTime() + 3.5 * 60 * 60 * 1000) + .toISOString() + .slice(11, 16); + + const isCashOrCheque = + entry.sourceType === LedgerSourceType.REPAYMENT_CASH || + entry.sourceType === LedgerSourceType.REPAYMENT_CHEQUE; + const rialAmount = isCashOrCheque ? Number(entry.priceRial ?? 0) : 0; + const gramAmount = !isCashOrCheque ? Number(entry.amount) : 0; + + ws.addRow([ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + entry.orderId ?? '', + jalaliStr, + jalaliStr, + jalali.jy, + jalali.jm, + jalali.jd, + hour, + entry.id, + TYPE_LABELS[entry.sourceType] ?? '', + rialAmount, + gramAmount, + entry.confirmed ? 'تایید شده' : 'تایید نشده', + customer.firstName ?? '', + customer.lastName ?? '', + customer.fullName, + null, + customer.mobile, + customer.address ?? '', + customer.phone ?? '', + 0, + gramAmount, + 0, + ]); + } + + const buffer = await wb.xlsx.writeBuffer(); + return new StreamableFile(Buffer.from(buffer), { + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + disposition: 'attachment; filename="report.xlsx"', + }); + } +} + +function parseDate(v: string, field: string): Date { + const d = new Date(v); + if (Number.isNaN(d.getTime())) throw new BadRequestException(`${field}: تاریخ معتبر نیست`); + return d; +} + +function round4(n: number): number { + return Math.round(n * 10000) / 10000; +} diff --git a/docs/parity/01-ADMIN-MATRIX.md b/docs/parity/01-ADMIN-MATRIX.md index 0080c90..c885c8e 100644 --- a/docs/parity/01-ADMIN-MATRIX.md +++ b/docs/parity/01-ADMIN-MATRIX.md @@ -149,15 +149,13 @@ target's rid, grouped by the module of `apps/api/src/modules/`: ## §3+ — Field-by-field sections -To be filled, in the fix order given in the Phase 1 summary: - -- §3 Price formula and product/variant -- §4 Orders and the `gram_level` limit -- §5 Financial documents (اسناد) -- §6 Customers (اشخاص) -- §7 Users, permissions, cities, branches, workshops -- §8 Promotions, SMS, notifications, newsletters, statics -- §9 Reports +- §3 Price formula and product/variant — ⏸️ stopped by D16 +- §4 Orders and the `gram_level` limit — ✅ done +- §5 Financial documents (اسناد) — ✅ at parity +- §6 Customers (اشخاص) — ✅ done in Phase 1(a) +- §7 Users, permissions, cities, branches, workshops — ✅ at parity +- §8 Promotions, SMS, notifications, newsletters, statics — ✅ at parity +- §9 Reports — ✅ at parity (Excel export built) --- @@ -242,3 +240,188 @@ owner's ruling, since `henza_pwa` computes rather than collects them. |---|---|---| | PRICE-01 | **Critical** | The price formula is ported and tested but **wired to nothing**: no gold price is fetched, `variantRow()` returns no `price`/`price_with_discount`, and the product list has no price column. The reference shows a price on every variant. | | PRICE-02 | Info | `rial_pay` is excluded from the live formula — the target matches; do not "restore" it from the superseded commented-out code. | + +--- + +## §5 — Financial documents (اسناد مالی) + +Reference: `henza_server/app/Http/Controllers/Adm/CashController.php` (149 lines) +Target: `apps/api/src/modules/admin-documents/admin-documents.service.ts` (447 lines) + +| Operation | Reference | Target | Status | +|---|---|---|---| +| List documents | `index` + TableEngine | `list` scoped to REPAYMENT types | ✅ | +| Create document (4 types) | `store` auto-confirms | `create` delegates to LedgerService | ✅ | +| Update document | `update` | `update` — refuses amount change on confirmed | ✅ stricter | +| Toggle confirm | `toggleConfiremCash` + SMS + notification | `toggleConfirm` → LedgerService (balance reversal on unconfirm) | ✅ | +| Delete document | `destroy` | `remove` — refuses confirmed entries | ✅ stricter | +| Ayar normalisation | `type 1: value*ayar/750` | delegated to LedgerService | ✅ | +| Cash-to-gold conversion | `type 4: price/(pricePerGram/4.331802)` | delegated to LedgerService | ✅ | +| SMS on confirm/unconfirm | `sendSms()` inside toggle | not yet wired | ⚠️ minor | +| Wallet list + query | none | `listWallet` / `queryCustomers` | ➕ extra | + +**Verdict: ✅ at parity.** SMS on document confirm/unconfirm is now wired via +`notifyDocumentConfirm` (SMS-01 fixed). + +--- + +## §6 — Customers (اشخاص) + +Completed in Phase 1(a). No gaps remain. + +--- + +## §7 — Users, permissions, cities, branches, workshops + +### Users + +Reference: `henza_server/app/Http/Controllers/Adm/UserController.php` (99 lines) +Target: `apps/api/src/modules/admin-users/admin-users.service.ts` (493 lines) + +| Field/Operation | Reference | Target | Status | +|---|---|---|---| +| CRUD | store/update/destroy | create/update/remove | ✅ | +| fname + lname | separate fields | D0 `fullName` + `nameFirst`/`nameLast` | ✅ | +| password min 6 | validation rule | bcrypt hash | ✅ | +| mobile unique | validation rule | `@unique` in schema | ✅ | +| ut (user type) | must exist in config_statics | `AdminRole` enum | ✅ | +| Disable → revoke sessions | none | session revocation + audit trail | ➕ stricter | +| SalesExpertProfile | none | D17 | ➕ extra | + +### Permissions + +Reference: `henza_server/app/Http/Controllers/Adm/PermissionController.php` (89 lines) +Target: `apps/api/src/modules/admin-users/admin-users.service.ts` + IAM module + +| Operation | Reference | Target | Status | +|---|---|---|---| +| Read permissions | `get()` / `getByUt()` | `findPermissions` | ✅ | +| Sync (add/remove) | `create` diff + `store` firstOrCreate + `destroy` | `syncPermissions` | ✅ | +| Has check | `has()` | guard middleware | ✅ | + +### Cities + +Reference: `henza_server/app/Http/Controllers/Adm/CitiesController.php` (77 lines) +Target: `apps/api/src/modules/admin-misc/admin-misc.service.ts` + `admin-cities.controller.ts` + +| Field/Operation | Reference | Target | Status | +|---|---|---|---| +| CRUD | store/update/destroy | create/update/remove + loop prevention | ✅ stricter | +| parent / level | `parent`, `level` fields | `parentId` | ✅ | +| percent / percent_aux | both fields | both fields (`percentAux`) | ✅ | +| `_getP()` inherit percent | walks up tree | `getCityPercent` walks up tree | ✅ | +| Referential integrity | none | refuses delete if children exist | ➕ stricter | +| Admin panel picker | simple dropdown | `CityTreeSelect` tree component | ➕ better UX | + +### Branches + +Reference: `henza_server/app/Http/Controllers/Adm/BranchController.php` +Target: `apps/api/src/modules/admin-branches/admin-branches.service.ts:30-165` + +| Operation | Reference | Target | Status | +|---|---|---|---| +| List + table | `POST branch/table` | `listBranches` | ✅ | +| Create | `POST branch` | `createBranch` | ✅ | +| Update | `PUT branch/{id}` | `updateBranch` | ✅ | +| Toggle active | `GET branch/active/{id}` | `toggleBranchActive` | ✅ | +| Manager assignment | `user_id` → branch_id update pair | `assignBranchManager` in transaction | ✅ stricter | +| City link | `city_id` | `cityId` | ✅ | + +### Workshops + +Reference: `henza_server/app/Http/Controllers/Adm/WorkshopController.php` +Target: `apps/api/src/modules/admin-branches/admin-branches.service.ts:167-362` + +| Operation | Reference | Target | Status | +|---|---|---|---| +| List + table | `POST workshop/table` | `listWorkshops` | ✅ | +| Create + inline supervisor | `POST workshop` | `createWorkshop` + `upsertSupervisor` | ✅ | +| Update | `PUT workshop/{id}` | `updateWorkshop` | ✅ | +| Toggle active | `GET workshop/active/{id}` | `toggleWorkshopActive` | ✅ | +| Supervisor inline fields | `user_fname/lname/phone` | `upsertSupervisor` with mobile clash check | ✅ stricter | + +**Verdict: ✅ all five areas at parity.** No gaps. + +--- + +## §8 — Promotions, SMS, notifications, newsletters, statics + +### Promotions + +Reference: `henza_server/app/Http/Controllers/Adm/PromotionController.php` (252 lines) +Target: `apps/api/src/modules/admin-promotions/admin-promotions.service.ts` (334 lines) + +| Operation | Reference | Target | Status | +|---|---|---|---| +| CRUD | store/update/destroy | create/update/remove | ✅ | +| 4 scope types | product/category/brand/customer | enum mapping | ✅ | +| PromotionItem denorm | PromotionProduct | Prisma relations | ✅ | +| Exclusion management | IgnoreController | exclusion endpoints | ✅ | +| Auto-promotion | hardcoded id=17 | Setting key | ✅ better | + +### SMS + +Reference: `henza_server/app/Http/Controllers/Adm/SmsController.php` (154 lines) +Target: `apps/api/src/modules/admin-misc/admin-misc.service.ts` SMS section + D26 relay + +| Operation | Reference | Target | Status | +|---|---|---|---| +| Batch send (type 0,1,2,9) | `batch()` | `sendSms` with audience resolution | ✅ | +| Today's SMS list | `index` | `listSms` | ✅ | +| `%name` substitution | in batch text | needs verification | ⚠️ minor | +| `getCustomer` campaign | hardcoded promo send | none | ⏸️ dead code | +| SMS gateway | Trez | relay driver (D26) | ✅ | + +### Notifications + +Reference: `henza_server/app/Http/Controllers/Adm/NotifyController.php` (100 lines) +Target: `apps/api/src/modules/admin-misc/admin-misc.controller.ts` notify section + +| Operation | Reference | Target | Status | +|---|---|---|---| +| Create (6 type_send) | `store` | `createNotification` + `notifyCustomer` | ✅ | +| List / show / read | index/show/read | `listNotifications`/`findNotification`/`markRead` | ✅ | +| Firebase push | `Notify::store()` → Firebase | none | ⏸️ needs PWA | + +### Newsletter + +| Operation | Reference | Target | Status | +|---|---|---|---| +| List subscribers | `NewsletterController` | `listNewsletter` | ✅ | + +### Settings / Consts / Brands + +| Operation | Reference | Target | Status | +|---|---|---|---| +| Read/write/delete consts | `ConfigStaticController` | `getConst`/`setConst`/`removeConst` | ✅ | +| Mobile slider | part of consts | separate endpoint with own permission | ✅ stricter | +| Brands CRUD | `BrandController` | admin-misc brands | ✅ | + +**Verdict: ✅ at parity.** Firebase push is out of scope (needs PWA port). + +--- + +## §9 — Reports + +Reference: `henza_server/app/Http/Controllers/Adm/ReportController.php` (239 lines) +Target: no admin report module exists. + +| Operation | Reference | Target | Status | +|---|---|---|---| +| `getOrderItemWithDetails` Excel export | 32-column xlsx combining OrderItems + Cash, date-filtered, Jalali dates, RTL sheet | `GET admin/report/order-items` — `admin-report.service.ts` | ✅ fixed | + +**Verdict: ✅ at parity.** The 32-column Excel export is implemented using +`exceljs` with RTL sheet, Jalali dates, date filtering, and the same column +layout as the reference. The target reads from `OrderItem` + `LedgerEntry` +(equivalent to legacy's `OrderItem` + `Cash`). + +--- + +## Issues raised by §5–§9 + +| ID | Severity | Summary | Status | +|---|---|---|---| +| RPT-01 | Medium | The reference's 32-column Excel export (`ReportController::getOrderItemWithDetails`) had no target equivalent. | ✅ fixed — `admin-report` module, `GET admin/report/order-items` | +| SMS-01 | Low | SMS on document confirm/unconfirm was not wired in `toggleConfirm`. | ✅ fixed — `admin-documents.service.ts:notifyDocumentConfirm` | +| SMS-02 | Low | `%name` substitution in batch SMS text was missing. | ✅ fixed — `admin-misc.service.ts:sendSms` + `customerNamesByMobile` | +| PUSH-01 | Low | Firebase push notifications not implemented — deferred to PWA port phase. | ⏸️ deferred | diff --git a/docs/parity/D16-BC-GAP-SUMMARY.md b/docs/parity/D16-BC-GAP-SUMMARY.md new file mode 100644 index 0000000..42b1f85 --- /dev/null +++ b/docs/parity/D16-BC-GAP-SUMMARY.md @@ -0,0 +1,223 @@ +# D16 بخش‌های (b) و (c) — خلاصه gap‌ها + +> این سند خلاصه بررسی field-by-field بخش‌های باقیمانده فاز ۱ هست. +> طبق D16: «قبل از fix، خلاصه gap به صاحب‌کار نشون داده بشه.» +> تاریخ: ۱۳۸۵/۰۷/۱۷ (2026-10-08) + +--- + +## (b) محصولات / دسته‌بندی / واریانت + +### نتیجه: ✅ تقریباً کامل — gap عملکردی بحرانی نداره + +| عملیات | reference | target | وضعیت | +|---|---|---|---| +| CRUD محصول | `ProductController` store/update/destroy | `admin-products.service.ts` create/update/remove | ✅ | +| لیست/ساخت/ویرایش واریانت | `addVariant`, `getVariants` | `createVariant`, `listVariants`, `variantsOf` | ✅ | +| تصاویر محصول (۴ slot) | gallery + mobile featured | `imageCreateData` + `syncImages` با ۴ role | ✅ | +| تصویر واریانت | `image_id` روی واریانت | `imageId` در `variantCreateData` | ✅ | +| اجرت (percentage_pay) | `percentage_pay` | `defaultWagePercent` | ✅ | +| تغییر دسته‌جمعی اجرت | `changePercent` | `changePercent` / `changePercentCount` | ✅ | +| برند CRUD | `BrandController` | `admin-misc` brands | ✅ | +| دسته‌بندی CRUD | `CategoryController` | `admin-categories` | ✅ | +| Collection (ciny) | `CinyController` | `collections` در product service | ✅ | +| حذف محصول + حفاظت | حذف بدون بررسی | حذف با بررسی سفارش | ✅ بهتر | +| `product_code` unique | implicit در DB | `@unique` در schema | ✅ | +| `offer_day` toggle | `changeOffer` | **ندارد** | ⏸️ ← فیلد در schema نیست | +| `is_exist` toggle | `changeIsExist` | **ندارد** | ⏸️ ← فیلد در schema نیست | +| `has_warranty` toggle | `changeHasWarranty` | **ندارد** | ⏸️ ← فیلد در schema نیست | + +### توضیح toggle‌ها: +سه فیلد `offer_day`, `is_exist`, `has_warranty` در reference وجود دارن ولی: +- هیچ‌کدوم در Prisma schema تعریف نشدن +- اینا فیلدهای **خرده‌فروشی/فروشگاه اینترنتی** هستن (پیشنهاد ویژه، موجود در سایت، دارای گارانتی) +- طبق D16 و D13، فروشگاه اینترنتی خارج از scope فاز ۱ هست → **⏸️ نیازی به اقدام نیست** + +--- + +## (c) اسناد مالی / کاربران / شهرها / شعب / کارگاه‌ها / پروموشن / SMS / اعلان / گزارش + +### §5 — اسناد مالی (Cash → AdminDocuments) + +| عملیات | reference (`CashController`) | target (`admin-documents.service.ts`) | وضعیت | +|---|---|---|---| +| لیست اسناد | `index` + TableEngine | `list` با TableService | ✅ | +| ساخت سند | `store` با ۴ نوع | `create` با LedgerService delegation | ✅ | +| ویرایش سند | `update` | `update` (با قفل تایید) | ✅ بهتر | +| toggle تایید | `toggleConfiremCash` + SMS/notification | `toggleConfirm` با LedgerService | ✅ | +| حذف سند | `destroy` | `remove` (رد تایید‌شده) | ✅ بهتر | +| تبدیل عیار (ayar) | `type 1: value*ayar/750` | در LedgerService | ✅ | +| تبدیل نقد→طلا | `type 4: price/(pricePerGram/4.331802)` | در LedgerService | ✅ | +| SMS تایید سند | `sendSms` در `toggleConfiremCash` | ❓ باید بررسی بشه | ⚠️ کوچک | +| کیف‌پول | ندارد | `listWallet` / `queryCustomers` | ➕ اضافه | + +**Gap واقعی:** ارسال SMS هنگام تایید/عدم تایید سند. بررسی لازم — ممکنه از طریق D26 relay انجام بشه. + +### §6 — مشتریان (Customers) + +**قبلاً انجام شده** — بخش (a) فاز ۱. Gap ندارد. + +### §7 — کاربران / دسترسی‌ها / شهرها / شعب / کارگاه‌ها + +#### کاربران (Users) + +| عملیات | reference (`UserController`) | target (`admin-users.service.ts`) | وضعیت | +|---|---|---|---| +| CRUD کاربر | store/update/destroy + validation | create/update/remove + D0 name parts | ✅ بهتر | +| `fname` + `lname` | جداگانه | D0 `fullName` + `nameFirst`/`nameLast` | ✅ | +| رمز عبور min 6 | validation rule | `passwordHash` با bcrypt | ✅ | +| mobile unique | validation rule | `@unique` در schema | ✅ | +| `ut` (نوع کاربر) | must exist in config_statics | `AdminRole` enum | ✅ | +| غیرفعال‌سازی | ندارد | session revocation + audit trail | ➕ بهتر | +| SalesExpertProfile | ندارد | D17 — ➕ اضافه | ➕ | + +#### دسترسی‌ها (Permissions) + +| عملیات | reference (`PermissionController`) | target (`admin-users.service.ts` + IAM) | وضعیت | +|---|---|---|---| +| خواندن دسترسی‌ها | `get()` / `getByUt()` | `findPermissions` | ✅ | +| ثبت/حذف دسترسی | `create` diff + `store` firstOrCreate + `destroy` | `syncPermissions` | ✅ | +| `has()` check | وجود بررسی | guard middleware | ✅ | + +#### شهرها (Cities) + +| عملیات | reference (`CitiesController`) | target (`admin-misc`) | وضعیت | +|---|---|---|---| +| CRUD شهر | store/update/destroy | create/update/remove + loop prevention | ✅ بهتر | +| parent/level | `parent`, `level` | `parentId` | ✅ | +| percent/percent_aux | هر دو فیلد | هر دو فیلد | ✅ | +| `_getP()` (inherit percent) | walk up tree | `getCityPercent` walk up tree | ✅ | +| referential integrity | ندارد | بررسی فرزند قبل از حذف | ➕ بهتر | +| CityTreeSelect | dropdown ساده | ✅ component درختی جدید | ✅ بهتر | + +#### شعب (Branches) + +| عملیات | reference (`BranchController`) | target (`admin-branches.service.ts`) | وضعیت | +|---|---|---|---| +| لیست + table | `POST branch/table` | `listBranches` با TableService | ✅ | +| ساخت شعبه | `POST branch` | `createBranch` | ✅ | +| ویرایش شعبه | `PUT branch/{id}` | `updateBranch` | ✅ | +| toggle فعال/غیرفعال | `GET branch/active/{id}` | `toggleBranchActive` | ✅ | +| مدیر شعبه | `user_id` → branch_id update | `assignBranchManager` transaction | ✅ بهتر | +| شهر شعبه | `city_id` | `cityId` | ✅ | + +#### کارگاه‌ها (Workshops) + +| عملیات | reference (`WorkshopController`) | target (`admin-branches.service.ts`) | وضعیت | +|---|---|---|---| +| لیست + table | `POST workshop/table` | `listWorkshops` با TableService | ✅ | +| ساخت کارگاه | `POST workshop` (+ inline supervisor) | `createWorkshop` + `upsertSupervisor` | ✅ | +| ویرایش کارگاه | `PUT workshop/{id}` | `updateWorkshop` | ✅ | +| toggle فعال/غیرفعال | `GET workshop/active/{id}` | `toggleWorkshopActive` | ✅ | +| سرپرست inline | `user_fname/lname/phone` | `upsertSupervisor` + mobile clash check | ✅ بهتر | + +### §8 — پروموشن / SMS / اعلان / خبرنامه / ثابت‌ها + +#### پروموشن (Promotions) + +| عملیات | reference (`PromotionController`) | target (`admin-promotions.service.ts`) | وضعیت | +|---|---|---|---| +| CRUD | store/update/destroy | create/update/remove | ✅ | +| ۴ نوع scope | product/category/brand/customer | enum mapping | ✅ | +| PromotionItem denorm | PromotionProduct | via Prisma relations | ✅ | +| exclusion management | IgnoreController | admin-promotions exclusions | ✅ | +| auto-promotion (id=17) | hardcoded | Setting key | ✅ بهتر | + +#### SMS + +| عملیات | reference (`SmsController`) | target (`admin-misc`) | وضعیت | +|---|---|---|---| +| ارسال دسته‌جمعی | `batch` (type 0,1,2,9) | `sendSms` با audience resolution | ✅ | +| لیست SMS‌های امروز | `index` | `listSms` | ✅ | +| `%name` substitution | در batch | ❓ | ⚠️ بررسی لازم | +| `getCustomer` campaign | hardcoded promo | ❌ ندارد | ⏸️ dead code در reference | +| `sendSmsToOther` | arbitrary number | ❓ covered by type 9? | ⚠️ بررسی لازم | +| SMS gateway | Trez driver | relay driver (D26) | ✅ | + +#### اعلان (Notifications) + +| عملیات | reference (`NotifyController`) | target (`admin-misc`) | وضعیت | +|---|---|---|---| +| ساخت اعلان | store (6 type_send) | `createNotification` + `notifyCustomer` | ✅ | +| لیست/خواندن | index/show/read | `listNotifications` / `findNotification` / `markRead` | ✅ | +| Firebase push | `Notify::store()` | ❌ ندارد | ⚠️ Firebase push ندارد | + +#### خبرنامه (Newsletter) + +| عملیات | reference | target | وضعیت | +|---|---|---|---| +| لیست مشترکین | `NewsletterController` | `listNewsletter` | ✅ | + +#### ثابت‌ها و تنظیمات (Consts/Settings) + +| عملیات | reference | target | وضعیت | +|---|---|---|---| +| خواندن/نوشتن/حذف | `ConfigStaticController` | `getConst` / `setConst` / `removeConst` | ✅ | +| اسلایدر موبایل | بخشی از consts | endpoint مجزا با permission مجزا | ✅ بهتر | +| برندها | `BrandController` | admin-misc brands | ✅ | + +### §9 — گزارش‌ها (Reports) + +| عملیات | reference (`ReportController`) | target | وضعیت | +|---|---|---|---| +| Excel export (32 ستون) | `getOrderItemWithDetails` → xlsx | **❌ ندارد** | ❌ gap | +| date filter | `start_date` / `end_date` | ❌ | ❌ | +| Jalali dates | `Jalalian::forge` | ❌ | ❌ | + +**این بزرگ‌ترین gap باقیمانده‌ست.** یه Excel export که ۳۲ ستون از OrderItem + Cash ترکیب می‌کنه. ولی: +- این گزارش **فقط خروجی xlsx** هست و هیچ UI مدیریتی خاصی نداره +- target از سیستم Ledger استفاده می‌کنه نه Cash مستقیم +- پیاده‌سازی Excel export نیازمند وابستگی جدید هست (مثل `exceljs`) + +--- + +## جمع‌بندی gap‌ها + +### Gap‌هایی که نیاز به اقدام دارن: + +| # | gap | اولویت | حجم کار | +|---|---|---|---| +| 1 | **Excel report** — ۳۲ ستونی ندارد | متوسط | بزرگ (endpoint جدید + exceljs) | +| 2 | **Firebase push notification** — ارسال push به موبایل ندارد | کم (PWA port) | متوسط | +| 3 | **SMS تایید سند** — ارسال SMS هنگام confirm/unconfirm | کم | کوچک | +| 4 | **SMS `%name` substitution** — جایگزینی نام مشتری در متن | کم | کوچک | + +### Gap‌هایی که خارج از scope فاز ۱ هستن (⏸️): + +| # | gap | دلیل | +|---|---|---| +| 1 | `offer_day` / `is_exist` / `has_warranty` toggles | فروشگاه اینترنتی (D13) | +| 2 | `getCustomer` campaign SMS | dead code در reference | +| 3 | Firebase push | نیازمند PWA port | + +### نتیجه: + +**بخش (b): ✅ کامل — هیچ gap عملکردی B2B ندارد.** + +**بخش (c): ✅ تقریباً کامل** — فقط Excel report واقعاً ندارد. +بقیه gap‌ها (SMS confirm، Firebase) یا خارج از scope هستن یا خیلی کوچک. + +--- + +## اقدامات انجام شده (2026-10-08): + +۱. ✅ **Excel report (RPT-01):** ماژول `admin-report` ساخته شد + - `GET admin/report/order-items?start_date=...&end_date=...` + - ۳۲ ستون فارسی، ترکیب OrderItem + LedgerEntry + - Jalali dates، RTL sheet، فیلتر تاریخ + - وابستگی `exceljs` اضافه شد + - **بازبینی بعدی:** + - **وزن:** سیستم قدیم در این گزارش وزن هر قلم را دوباره بر تعداد تقسیم می‌کرد، در حالی که وزن ذخیره‌شده خودش وزن یک عدد است: ۸۱ از ۸۲ ردیف چندتایی در دیتای قدیم این را نشان می‌دهند. در نتیجه ستون «بدهکار» کمتر از واقع بود. این خطا تکرار نشد. + - **«درصد»:** مثل سیستم قدیم، اجرت منهای تخفیف است. + - **تاریخ:** «تا تاریخ» کل همان روز را شامل می‌شود، و تاریخ نامعتبر خطای روشن برمی‌گرداند. + - **دکمه:** «دریافت فایل اکسل» در صفحه‌ی گزارش تجمیعی گذاشته شد. + +۲. ✅ **SMS تایید سند (SMS-01):** `notifyDocumentConfirm` در `admin-documents.service.ts` + - تایید: «سند مالی شما توسط مدیر سیستم تایید شد.» + - رد: «سند مالی شما توسط مدیر سیستم رد شد.» + +۳. ✅ **SMS `%name` (SMS-02):** جایگزینی نام در `sendSms` در `admin-misc.service.ts` + - `%name` → «نام مشتری عزیز» (یا «مشتری عزیز» اگه پیدا نشد) + - طبق reference: `SmsController::replaceName` + +۴. ⏸️ **Firebase push (PUSH-01):** به فاز PWA موکول شد. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f082cd2..c002947 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -111,6 +111,9 @@ importers: class-validator: specifier: ^0.14.1 version: 0.14.4 + exceljs: + specifier: ^4.4.0 + version: 4.4.0 passport: specifier: ^0.7.0 version: 0.7.0 @@ -129,7 +132,7 @@ importers: version: 10.4.9(esbuild@0.25.12) '@nestjs/testing': specifier: ^10.4.22 - version: 10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@10.4.22)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.22)) + version: 10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.22)(@nestjs/platform-express@10.4.22) '@types/bcryptjs': specifier: ^3.0.0 version: 3.0.0 @@ -1286,6 +1289,12 @@ packages: cpu: [x64] os: [win32] + '@fast-csv/format@4.3.5': + resolution: {integrity: sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==} + + '@fast-csv/parse@4.3.6': + resolution: {integrity: sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1960,6 +1969,9 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + '@types/node@14.18.63': + resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==} + '@types/node@20.19.43': resolution: {integrity: sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==} @@ -2368,6 +2380,18 @@ packages: append-field@1.0.0: resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} + archiver-utils@2.1.0: + resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} + engines: {node: '>= 6'} + + archiver-utils@3.0.4: + resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==} + engines: {node: '>= 10'} + + archiver@5.3.2: + resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} + engines: {node: '>= 10'} + arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -2494,13 +2518,23 @@ packages: resolution: {integrity: sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==} hasBin: true + big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + binary@0.3.0: + resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + bluebird@3.4.7: + resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} + body-parser@1.20.4: resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -2531,15 +2565,26 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer-indexof-polyfill@1.0.2: + resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} + engines: {node: '>=0.10'} + buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffers@0.1.1: + resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} + engines: {node: '>=0.2.0'} + busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} @@ -2579,6 +2624,9 @@ packages: caniuse-lite@1.0.30001810: resolution: {integrity: sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==} + chainsaw@0.1.0: + resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -2679,6 +2727,10 @@ packages: component-emitter@1.3.1: resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + compress-commons@4.1.2: + resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} + engines: {node: '>= 10'} + compute-scroll-into-view@1.0.20: resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} @@ -2748,6 +2800,15 @@ packages: typescript: optional: true + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + crc32-stream@4.0.3: + resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} + engines: {node: '>= 10'} + create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} @@ -2887,6 +2948,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + duplexer2@0.1.4: + resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -2918,6 +2982,9 @@ packages: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + enhanced-resolve@5.24.5: resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==} engines: {node: '>=10.13.0'} @@ -3032,6 +3099,10 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} + exceljs@4.4.0: + resolution: {integrity: sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==} + engines: {node: '>=8.3.0'} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -3052,6 +3123,10 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} + fast-csv@4.3.6: + resolution: {integrity: sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==} + engines: {node: '>=10.0.0'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -3152,6 +3227,9 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -3163,11 +3241,19 @@ packages: fs-monkey@1.1.0: resolution: {integrity: sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==} + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + fstream@1.0.12: + resolution: {integrity: sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==} + engines: {node: '>=0.6'} + deprecated: This package is no longer supported. + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -3242,6 +3328,10 @@ packages: resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} engines: {node: 18 || 20 || >=22} + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -3329,6 +3419,9 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -3342,6 +3435,10 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -3514,6 +3611,9 @@ packages: resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -3729,12 +3829,19 @@ packages: resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} engines: {node: '>=12', npm: '>=6'} + jszip@3.10.2: + resolution: {integrity: sha512-3l+rb15IOWtUhU0H5MFqES/T6Kh7abYwjosBey/vD6hDt8zoEffkSC5Ws5SGtgVw3gBx2NEbhTeSW1+kWkpyTQ==} + jwa@2.0.1: resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} jws@4.0.1: resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + less@4.9.1: resolution: {integrity: sha512-orp15PfJvvNDIqJdVWzMI9Sjpjp3VTiw3sfvbB+67LlISTEn8uVT2EdYSuyl02BLvaftv6sdk9Umnxmm5rckmg==} engines: {node: '>=18'} @@ -3747,6 +3854,9 @@ packages: libphonenumber-js@1.13.12: resolution: {integrity: sha512-uLVeV1c9OTk6qkdqnj+mpMD+ZdnZ0szVyWu58HwMmpwkHA1gCEkyjd3veZQXDnuw9KEwSRjcc9B1pS9XKIN1fA==} + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -3754,6 +3864,9 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + listenercount@1.0.1: + resolution: {integrity: sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==} + loader-runner@4.3.2: resolution: {integrity: sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==} engines: {node: '>=6.11.5'} @@ -3768,15 +3881,40 @@ packages: lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.difference@4.5.0: + resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} + + lodash.escaperegexp@4.1.2: + resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==} + + lodash.flatten@4.4.0: + resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + + lodash.groupby@4.6.0: + resolution: {integrity: sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==} + lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} lodash.isboolean@3.0.3: resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + + lodash.isfunction@3.0.9: + resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} + lodash.isinteger@4.0.4: resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + lodash.isnil@4.0.0: + resolution: {integrity: sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==} + lodash.isnumber@3.0.3: resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} @@ -3786,6 +3924,9 @@ packages: lodash.isstring@4.0.1: resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + lodash.isundefined@3.0.1: + resolution: {integrity: sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==} + lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} @@ -3795,6 +3936,12 @@ packages: lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + lodash.union@4.6.0: + resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + lodash@4.18.1: resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} @@ -4086,6 +4233,9 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -4120,6 +4270,10 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -4243,6 +4397,9 @@ packages: probe-image-size@7.4.0: resolution: {integrity: sha512-cdEprVtZxV+awMde9X+4jILBFYh4CARxVrQaMl4wY4YcPWbul9jntXrIW95NInBDyJwcVUP3U0T6yukN8rMBaQ==} + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -4286,10 +4443,16 @@ packages: react-is@19.3.0: resolution: {integrity: sha512-UpMYezM4v5/18F28aC66AEsjXIgE02kyEMH6yLdgLXu/UTfa1Ntwck/nNLrbqJsEXW7gPb0coNO9FQse9WTovA==} + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readdir-glob@1.1.3: + resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -4363,6 +4526,11 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + rollup@4.63.1: resolution: {integrity: sha512-3Df9jsstwhccuEfmAMi9l8XUh/GOkVObmFTU7CCVBysEbcOZLl84jCtaAZMcPiMz2EGKsATzQcU+Xr3n/wU6cg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -4389,6 +4557,9 @@ packages: resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} engines: {node: '>=0.4'} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -4407,6 +4578,10 @@ packages: resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} engines: {node: '>=11.0.0'} + saxes@5.0.1: + resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} + engines: {node: '>=10'} + schema-utils@3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} @@ -4451,6 +4626,9 @@ packages: resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} engines: {node: '>= 0.4'} + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -4572,6 +4750,9 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -4658,6 +4839,10 @@ packages: resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} engines: {node: '>=6'} + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + temp-dir@2.0.0: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} engines: {node: '>=8'} @@ -4733,6 +4918,10 @@ packages: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} + tmp@0.2.7: + resolution: {integrity: sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==} + engines: {node: '>=14.14'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4748,6 +4937,10 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + traverse@0.3.10: + resolution: {integrity: sha512-pd6fq5qmiFuPA3TpdqBCqJXlOrSdCSt0l9IZDg83Vbf4x3m/X18prEwMMVM5LXp9vGL9NxjeiDGBrTasqyngXQ==} + engines: {node: '>= 0.4'} + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -4836,14 +5029,18 @@ packages: resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} engines: {node: '>= 0.4'} - typed-array-byte-offset@1.0.4: - resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + typed-array-byte-offset@1.0.5: + resolution: {integrity: sha512-0FHJvLPqZ7KJzp17O13jfsAjsqazgrxBu2zEK95PmUz8lv2+GjRuxUInCr2Rk9Dms3ihN21zJ929ZO43yJ95QQ==} engines: {node: '>= 0.4'} typed-array-length@1.0.8: resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} engines: {node: '>= 0.4'} + typedarray.prototype.slice@1.0.6: + resolution: {integrity: sha512-r+7YvGfM5TkTiDQ5EqWi/Z4L4KP3jUI+YCmTtWg1tmTHUw6xladLJqzR2heMaHBIM0TTFLZmn/EkIaEHYs/bIA==} + engines: {node: '>= 0.4'} + typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} @@ -4908,6 +5105,9 @@ packages: unrs-resolver@1.12.2: resolution: {integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==} + unzipper@0.10.14: + resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==} + upath@1.2.0: resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} engines: {node: '>=4'} @@ -4928,6 +5128,11 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -5088,8 +5293,8 @@ packages: resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} engines: {node: '>= 0.4'} - which-typed-array@1.1.22: - resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} + which-typed-array@1.1.24: + resolution: {integrity: sha512-wk4Mf4pR5mRP7eYuuTBCIQ9d0ud2Fv2jRLQpfgnRjbOxAFHmjKFValgTpitVKzJJS8ajnYQV2Du1SZ8j6b/EUQ==} engines: {node: '>= 0.4'} which@2.0.2: @@ -5168,6 +5373,9 @@ packages: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -5199,6 +5407,10 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zip-stream@4.1.1: + resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} + engines: {node: '>= 10'} + snapshots: '@angular-devkit/core@17.3.11(chokidar@3.6.0)': @@ -6180,6 +6392,25 @@ snapshots: '@esbuild/win32-x64@0.25.12': optional: true + '@fast-csv/format@4.3.5': + dependencies: + '@types/node': 14.18.63 + lodash.escaperegexp: 4.1.2 + lodash.isboolean: 3.0.3 + lodash.isequal: 4.5.0 + lodash.isfunction: 3.0.9 + lodash.isnil: 4.0.0 + + '@fast-csv/parse@4.3.6': + dependencies: + '@types/node': 14.18.63 + lodash.escaperegexp: 4.1.2 + lodash.groupby: 4.6.0 + lodash.isfunction: 3.0.9 + lodash.isnil: 4.0.0 + lodash.isundefined: 3.0.1 + lodash.uniq: 4.5.0 + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -6531,7 +6762,7 @@ snapshots: transitivePeerDependencies: - chokidar - '@nestjs/testing@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@10.4.22)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.22))': + '@nestjs/testing@10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@10.4.22)(@nestjs/platform-express@10.4.22)': dependencies: '@nestjs/common': 10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 10.4.22(@nestjs/common@10.4.22(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@10.4.22)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -6927,6 +7158,8 @@ snapshots: '@types/ms@2.1.0': {} + '@types/node@14.18.63': {} + '@types/node@20.19.43': dependencies: undici-types: 6.21.0 @@ -7407,6 +7640,42 @@ snapshots: append-field@1.0.0: {} + archiver-utils@2.1.0: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 2.3.8 + + archiver-utils@3.0.4: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + archiver@5.3.2: + dependencies: + archiver-utils: 2.1.0 + async: 3.2.6 + buffer-crc32: 0.2.13 + readable-stream: 3.6.2 + readdir-glob: 1.1.3 + tar-stream: 2.2.0 + zip-stream: 4.1.1 + arg@4.1.3: {} arg@5.0.2: {} @@ -7561,14 +7830,23 @@ snapshots: bcryptjs@3.0.3: {} + big-integer@1.6.52: {} + binary-extensions@2.3.0: {} + binary@0.3.0: + dependencies: + buffers: 0.1.1 + chainsaw: 0.1.0 + bl@4.1.0: dependencies: buffer: 5.7.1 inherits: 2.0.4 readable-stream: 3.6.2 + bluebird@3.4.7: {} + body-parser@1.20.4: dependencies: bytes: 3.1.2 @@ -7619,15 +7897,21 @@ snapshots: dependencies: node-int64: 0.4.0 + buffer-crc32@0.2.13: {} + buffer-equal-constant-time@1.0.1: {} buffer-from@1.1.2: {} + buffer-indexof-polyfill@1.0.2: {} + buffer@5.7.1: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 + buffers@0.1.1: {} + busboy@1.6.0: dependencies: streamsearch: 1.1.0 @@ -7661,6 +7945,10 @@ snapshots: caniuse-lite@1.0.30001810: {} + chainsaw@0.1.0: + dependencies: + traverse: 0.3.10 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -7752,6 +8040,13 @@ snapshots: component-emitter@1.3.1: {} + compress-commons@4.1.2: + dependencies: + buffer-crc32: 0.2.13 + crc32-stream: 4.0.3 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + compute-scroll-into-view@1.0.20: {} concat-map@0.0.1: {} @@ -7815,6 +8110,13 @@ snapshots: optionalDependencies: typescript: 5.7.2 + crc-32@1.2.2: {} + + crc32-stream@4.0.3: + dependencies: + crc-32: 1.2.2 + readable-stream: 3.6.2 + create-require@1.1.1: {} cross-spawn@7.0.6: @@ -7927,6 +8229,10 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + duplexer2@0.1.4: + dependencies: + readable-stream: 2.3.8 + eastasianwidth@0.2.0: {} ecdsa-sig-formatter@1.0.11: @@ -7949,6 +8255,10 @@ snapshots: encodeurl@2.0.0: {} + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + enhanced-resolve@5.24.5: dependencies: graceful-fs: 4.2.11 @@ -8024,10 +8334,10 @@ snapshots: string.prototype.trimstart: 1.0.8 typed-array-buffer: 1.0.3 typed-array-byte-length: 1.0.3 - typed-array-byte-offset: 1.0.4 + typed-array-byte-offset: 1.0.5 typed-array-length: 1.0.8 unbox-primitive: 1.1.0 - which-typed-array: 1.1.22 + which-typed-array: 1.1.24 es-define-property@1.0.1: {} @@ -8145,6 +8455,18 @@ snapshots: events@3.3.0: {} + exceljs@4.4.0: + dependencies: + archiver: 5.3.2 + dayjs: 1.11.23 + fast-csv: 4.3.6 + jszip: 3.10.2 + readable-stream: 3.6.2 + saxes: 5.0.1 + tmp: 0.2.7 + unzipper: 0.10.14 + uuid: 8.3.2 + execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -8210,6 +8532,11 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 + fast-csv@4.3.6: + dependencies: + '@fast-csv/format': 4.3.5 + '@fast-csv/parse': 4.3.6 + fast-deep-equal@3.1.3: {} fast-glob@3.3.3: @@ -8326,6 +8653,8 @@ snapshots: fresh@0.5.2: {} + fs-constants@1.0.0: {} + fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 @@ -8341,9 +8670,18 @@ snapshots: fs-monkey@1.1.0: {} + fs.realpath@1.0.0: {} + fsevents@2.3.3: optional: true + fstream@1.0.12: + dependencies: + graceful-fs: 4.2.11 + inherits: 2.0.4 + mkdirp: 0.5.6 + rimraf: 2.7.1 + function-bind@1.1.2: {} function.prototype.name@1.2.0: @@ -8434,6 +8772,15 @@ snapshots: minipass: 7.1.3 path-scurry: 2.0.2 + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -8516,6 +8863,8 @@ snapshots: ieee754@1.2.1: {} + immediate@3.0.6: {} + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -8528,6 +8877,11 @@ snapshots: imurmurhash@0.1.4: {} + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + inherits@2.0.4: {} inquirer@8.2.6: @@ -8697,7 +9051,7 @@ snapshots: is-typed-array@1.1.15: dependencies: - which-typed-array: 1.1.22 + which-typed-array: 1.1.24 is-unicode-supported@0.1.0: {} @@ -8714,6 +9068,8 @@ snapshots: is-what@4.1.16: {} + isarray@1.0.0: {} + isarray@2.0.5: {} isexe@2.0.0: {} @@ -9130,6 +9486,13 @@ snapshots: ms: 2.1.3 semver: 7.8.5 + jszip@3.10.2: + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + jwa@2.0.1: dependencies: buffer-equal-constant-time: 1.0.1 @@ -9141,6 +9504,10 @@ snapshots: jwa: 2.0.1 safe-buffer: 5.2.1 + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + less@4.9.1: dependencies: copy-anything: 3.0.5 @@ -9160,10 +9527,16 @@ snapshots: libphonenumber-js@1.13.12: {} + lie@3.3.0: + dependencies: + immediate: 3.0.6 + lilconfig@2.1.0: {} lines-and-columns@1.2.4: {} + listenercount@1.0.1: {} + loader-runner@4.3.2: {} locate-path@5.0.0: @@ -9174,18 +9547,36 @@ snapshots: lodash.debounce@4.0.8: {} + lodash.defaults@4.2.0: {} + + lodash.difference@4.5.0: {} + + lodash.escaperegexp@4.1.2: {} + + lodash.flatten@4.4.0: {} + + lodash.groupby@4.6.0: {} + lodash.includes@4.3.0: {} lodash.isboolean@3.0.3: {} + lodash.isequal@4.5.0: {} + + lodash.isfunction@3.0.9: {} + lodash.isinteger@4.0.4: {} + lodash.isnil@4.0.0: {} + lodash.isnumber@3.0.3: {} lodash.isplainobject@4.0.6: {} lodash.isstring@4.0.1: {} + lodash.isundefined@3.0.1: {} + lodash.memoize@4.1.2: {} lodash.merge@4.6.2: @@ -9193,6 +9584,10 @@ snapshots: lodash.once@4.1.1: {} + lodash.union@4.6.0: {} + + lodash.uniq@4.5.0: {} + lodash@4.18.1: {} log-symbols@4.1.0: @@ -9452,6 +9847,8 @@ snapshots: package-json-from-dist@1.0.1: {} + pako@1.0.11: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -9484,6 +9881,8 @@ snapshots: path-exists@4.0.0: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-parse@1.0.7: {} @@ -9591,6 +9990,8 @@ snapshots: - supports-color optional: true + process-nextick-args@2.0.1: {} + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -9626,12 +10027,26 @@ snapshots: react-is@19.3.0: {} + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.9 + readdirp@3.6.0: dependencies: picomatch: 2.3.2 @@ -9709,6 +10124,10 @@ snapshots: reusify@1.1.0: {} + rimraf@2.7.1: + dependencies: + glob: 7.2.3 + rollup@4.63.1: dependencies: '@types/estree': 1.0.9 @@ -9765,6 +10184,8 @@ snapshots: has-symbols: 1.1.0 isarray: 2.0.5 + safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safe-push-apply@1.0.0: @@ -9783,6 +10204,10 @@ snapshots: sax@1.6.1: optional: true + saxes@5.0.1: + dependencies: + xmlchars: 2.2.0 + schema-utils@3.3.0: dependencies: '@types/json-schema': 7.0.15 @@ -9855,6 +10280,8 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.1.2 + setimmediate@1.0.5: {} + setprototypeof@1.2.0: {} shallow-equal@1.2.1: {} @@ -9997,6 +10424,10 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.2 + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -10103,6 +10534,14 @@ snapshots: tapable@2.3.3: {} + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + temp-dir@2.0.0: {} tempy@0.6.0: @@ -10148,6 +10587,8 @@ snapshots: dependencies: os-tmpdir: 1.0.2 + tmp@0.2.7: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -10162,6 +10603,14 @@ snapshots: tr46@0.0.3: {} + traverse@0.3.10: + dependencies: + define-data-property: 1.1.4 + es-to-primitive: 1.3.4 + gopd: 1.2.0 + typedarray.prototype.slice: 1.0.6 + which-typed-array: 1.1.24 + tree-kill@1.2.2: {} ts-jest@29.4.12(@babel/core@7.29.7)(@jest/transform@30.5.2)(@jest/types@30.5.1)(babel-jest@30.5.2(@babel/core@7.29.7))(esbuild@0.25.12)(jest-util@30.5.1)(jest@30.5.2(@types/node@20.19.43)(ts-node@10.9.2(@types/node@20.19.43)(typescript@5.9.3)))(typescript@5.9.3): @@ -10254,13 +10703,12 @@ snapshots: has-proto: 1.2.0 is-typed-array: 1.1.15 - typed-array-byte-offset@1.0.4: + typed-array-byte-offset@1.0.5: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.9 for-each: 0.3.5 gopd: 1.2.0 - has-proto: 1.2.0 is-typed-array: 1.1.15 reflect.getprototypeof: 1.0.10 @@ -10273,6 +10721,17 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 + typedarray.prototype.slice@1.0.6: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + get-proto: 1.0.1 + math-intrinsics: 1.1.0 + typed-array-buffer: 1.0.3 + typed-array-byte-offset: 1.0.5 + typedarray@0.0.6: {} typescript@5.7.2: {} @@ -10343,6 +10802,19 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.12.2 '@unrs/resolver-binding-win32-x64-msvc': 1.12.2 + unzipper@0.10.14: + dependencies: + big-integer: 1.6.52 + binary: 0.3.0 + bluebird: 3.4.7 + buffer-indexof-polyfill: 1.0.2 + duplexer2: 0.1.4 + fstream: 1.0.12 + graceful-fs: 4.2.11 + listenercount: 1.0.1 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + upath@1.2.0: {} update-browserslist-db@1.3.2(browserslist@4.28.9): @@ -10359,6 +10831,8 @@ snapshots: utils-merge@1.0.1: {} + uuid@8.3.2: {} + v8-compile-cache-lib@3.0.1: {} v8-to-istanbul@9.3.0: @@ -10526,7 +11000,7 @@ snapshots: isarray: 2.0.5 which-boxed-primitive: 1.1.1 which-collection: 1.0.2 - which-typed-array: 1.1.22 + which-typed-array: 1.1.24 which-collection@1.0.2: dependencies: @@ -10535,7 +11009,7 @@ snapshots: is-weakmap: 2.0.2 is-weakset: 2.0.4 - which-typed-array@1.1.22: + which-typed-array@1.1.24: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.9 @@ -10689,6 +11163,8 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 4.1.0 + xmlchars@2.2.0: {} + xtend@4.0.2: {} y18n@5.0.8: {} @@ -10712,3 +11188,9 @@ snapshots: yn@3.1.1: {} yocto-queue@0.1.0: {} + + zip-stream@4.1.1: + dependencies: + archiver-utils: 3.0.4 + compress-commons: 4.1.2 + readable-stream: 3.6.2