Refactor integration services and update import paths to align with the new domain structure, enhancing type safety and maintainability. Streamline Freebit integration by utilizing updated provider methods and removing deprecated types. Improve organization and consistency in data handling across various modules, including catalog and billing services.
This commit is contained in:
parent
69aa47ad59
commit
12c3dc976f
@ -1,4 +1,4 @@
|
|||||||
import type { SalesforceProductFieldMap } from "@customer-portal/domain";
|
import type { SalesforceProductFieldMap } from "@customer-portal/domain/billing";
|
||||||
import { Injectable } from "@nestjs/common";
|
import { Injectable } from "@nestjs/common";
|
||||||
import { ConfigService } from "@nestjs/config";
|
import { ConfigService } from "@nestjs/config";
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import type {
|
|||||||
FreebitConfig,
|
FreebitConfig,
|
||||||
FreebitAuthRequest,
|
FreebitAuthRequest,
|
||||||
FreebitAuthResponse,
|
FreebitAuthResponse,
|
||||||
} from "../interfaces/freebit.types";
|
} from "@customer-portal/domain/sim/providers/freebit";
|
||||||
import { FreebitError } from "./freebit-error.service";
|
import { FreebitError } from "./freebit-error.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|||||||
@ -26,7 +26,6 @@ import type {
|
|||||||
FreebitAccountDetailsRequest,
|
FreebitAccountDetailsRequest,
|
||||||
FreebitTrafficInfoRequest,
|
FreebitTrafficInfoRequest,
|
||||||
FreebitQuotaHistoryRequest,
|
FreebitQuotaHistoryRequest,
|
||||||
FreebitQuotaHistoryResponse,
|
|
||||||
FreebitEsimAddAccountRequest,
|
FreebitEsimAddAccountRequest,
|
||||||
} from "@customer-portal/domain/sim/providers/freebit";
|
} from "@customer-portal/domain/sim/providers/freebit";
|
||||||
import type { SimDetails, SimTopUpHistory, SimUsage } from "@customer-portal/domain/sim";
|
import type { SimDetails, SimTopUpHistory, SimUsage } from "@customer-portal/domain/sim";
|
||||||
@ -200,7 +199,7 @@ export class FreebitOperationsService {
|
|||||||
|
|
||||||
const response = await this.client.makeAuthenticatedRequest<
|
const response = await this.client.makeAuthenticatedRequest<
|
||||||
FreebitQuotaHistoryResponse,
|
FreebitQuotaHistoryResponse,
|
||||||
typeof request
|
FreebitQuotaHistoryRequest
|
||||||
>("/mvno/getQuotaHistory/", request);
|
>("/mvno/getQuotaHistory/", request);
|
||||||
|
|
||||||
return this.mapper.mapToSimTopUpHistory(response, account);
|
return this.mapper.mapToSimTopUpHistory(response, account);
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
type AccountData,
|
type AccountData,
|
||||||
type UpsertResult,
|
type UpsertResult,
|
||||||
} from "./services/salesforce-account.service";
|
} from "./services/salesforce-account.service";
|
||||||
import type { SalesforceAccountRecord, SalesforceOrderRecord } from "@customer-portal/domain";
|
import type { SalesforceAccountRecord, SalesforceOrderRecord } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean Salesforce Service - Only includes actually used functionality
|
* Clean Salesforce Service - Only includes actually used functionality
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Injectable, Inject } from "@nestjs/common";
|
|||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util";
|
import { getErrorMessage } from "@bff/core/utils/error.util";
|
||||||
import { SalesforceConnection } from "./salesforce-connection.service";
|
import { SalesforceConnection } from "./salesforce-connection.service";
|
||||||
import type { SalesforceAccountRecord, SalesforceQueryResult } from "@customer-portal/domain";
|
import type { SalesforceAccountRecord, SalesforceQueryResult } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
export interface AccountData {
|
export interface AccountData {
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import type {
|
|||||||
SimCatalogProduct,
|
SimCatalogProduct,
|
||||||
SimActivationFeeCatalogItem,
|
SimActivationFeeCatalogItem,
|
||||||
VpnCatalogProduct,
|
VpnCatalogProduct,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import { InternetCatalogService } from "./services/internet-catalog.service";
|
import { InternetCatalogService } from "./services/internet-catalog.service";
|
||||||
import { SimCatalogService } from "./services/sim-catalog.service";
|
import { SimCatalogService } from "./services/sim-catalog.service";
|
||||||
import { VpnCatalogService } from "./services/vpn-catalog.service";
|
import { VpnCatalogService } from "./services/vpn-catalog.service";
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import type {
|
|||||||
SalesforceProduct2WithPricebookEntries,
|
SalesforceProduct2WithPricebookEntries,
|
||||||
SalesforcePricebookEntryRecord,
|
SalesforcePricebookEntryRecord,
|
||||||
SalesforceQueryResult,
|
SalesforceQueryResult,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BaseCatalogService {
|
export class BaseCatalogService {
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import type {
|
|||||||
InternetPlanCatalogItem,
|
InternetPlanCatalogItem,
|
||||||
InternetInstallationCatalogItem,
|
InternetInstallationCatalogItem,
|
||||||
InternetAddonCatalogItem,
|
InternetAddonCatalogItem,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import { MappingsService } from "@bff/modules/id-mappings/mappings.service";
|
import { MappingsService } from "@bff/modules/id-mappings/mappings.service";
|
||||||
import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service";
|
import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service";
|
||||||
import { SalesforceFieldMapService } from "@bff/core/config/field-map";
|
import { SalesforceFieldMapService } from "@bff/core/config/field-map";
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import type {
|
|||||||
SalesforceProduct2WithPricebookEntries,
|
SalesforceProduct2WithPricebookEntries,
|
||||||
SimCatalogProduct,
|
SimCatalogProduct,
|
||||||
SimActivationFeeCatalogItem,
|
SimActivationFeeCatalogItem,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import {
|
import {
|
||||||
mapSimProduct,
|
mapSimProduct,
|
||||||
mapSimActivationFee,
|
mapSimActivationFee,
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { BaseCatalogService } from "./base-catalog.service";
|
|||||||
import type {
|
import type {
|
||||||
SalesforceProduct2WithPricebookEntries,
|
SalesforceProduct2WithPricebookEntries,
|
||||||
VpnCatalogProduct,
|
VpnCatalogProduct,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import { mapVpnProduct } from "@bff/modules/catalog/utils/salesforce-product.mapper";
|
import { mapVpnProduct } from "@bff/modules/catalog/utils/salesforce-product.mapper";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|||||||
@ -7,11 +7,11 @@ import type {
|
|||||||
SimActivationFeeCatalogItem,
|
SimActivationFeeCatalogItem,
|
||||||
SimCatalogProduct,
|
SimCatalogProduct,
|
||||||
VpnCatalogProduct,
|
VpnCatalogProduct,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import type {
|
import type {
|
||||||
SalesforceProduct2WithPricebookEntries,
|
SalesforceProduct2WithPricebookEntries,
|
||||||
SalesforcePricebookEntryRecord,
|
SalesforcePricebookEntryRecord,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import type { SalesforceFieldMap } from "@bff/core/config/field-map";
|
import type { SalesforceFieldMap } from "@bff/core/config/field-map";
|
||||||
|
|
||||||
export type SalesforceCatalogProductRecord = SalesforceProduct2WithPricebookEntries;
|
export type SalesforceCatalogProductRecord = SalesforceProduct2WithPricebookEntries;
|
||||||
|
|||||||
@ -25,8 +25,8 @@ import type {
|
|||||||
PaymentGatewayList,
|
PaymentGatewayList,
|
||||||
InvoicePaymentLink,
|
InvoicePaymentLink,
|
||||||
InvoiceListQuery,
|
InvoiceListQuery,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import { invoiceListQuerySchema } from "@customer-portal/domain";
|
import { invoiceListQuerySchema } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface AuthenticatedRequest {
|
interface AuthenticatedRequest {
|
||||||
user: { id: string };
|
user: { id: string };
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import {
|
|||||||
Inject,
|
Inject,
|
||||||
} from "@nestjs/common";
|
} from "@nestjs/common";
|
||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
import { Invoice, InvoiceList } from "@customer-portal/domain";
|
import { Invoice, InvoiceList } from "@customer-portal/domain/billing";
|
||||||
import { WhmcsService } from "@bff/integrations/whmcs/whmcs.service";
|
import { WhmcsService } from "@bff/integrations/whmcs/whmcs.service";
|
||||||
import { MappingsService } from "@bff/modules/id-mappings/mappings.service";
|
import { MappingsService } from "@bff/modules/id-mappings/mappings.service";
|
||||||
import { getErrorMessage } from "@bff/core/utils/error.util";
|
import { getErrorMessage } from "@bff/core/utils/error.util";
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Injectable, Inject } from "@nestjs/common";
|
import { Injectable, Inject } from "@nestjs/common";
|
||||||
import { Logger } from "nestjs-pino";
|
import { Logger } from "nestjs-pino";
|
||||||
import { Invoice, InvoiceList } from "@customer-portal/domain";
|
import { Invoice, InvoiceList } from "@customer-portal/domain/billing";
|
||||||
import { InvoiceRetrievalService } from "./invoice-retrieval.service";
|
import { InvoiceRetrievalService } from "./invoice-retrieval.service";
|
||||||
import { InvoiceHealthService } from "./invoice-health.service";
|
import { InvoiceHealthService } from "./invoice-health.service";
|
||||||
import { InvoiceValidatorService } from "../validators/invoice-validator.service";
|
import { InvoiceValidatorService } from "../validators/invoice-validator.service";
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import {
|
|||||||
updateAddressRequestSchema,
|
updateAddressRequestSchema,
|
||||||
type UpdateProfileRequest,
|
type UpdateProfileRequest,
|
||||||
type UpdateAddressRequest,
|
type UpdateAddressRequest,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import type { RequestWithUser } from "@bff/modules/auth/auth.types";
|
import type { RequestWithUser } from "@bff/modules/auth/auth.types";
|
||||||
|
|
||||||
@Controller("me")
|
@Controller("me")
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { accountService } from "@/features/account/services/account.service";
|
|||||||
import { Sidebar } from "./Sidebar";
|
import { Sidebar } from "./Sidebar";
|
||||||
import { Header } from "./Header";
|
import { Header } from "./Header";
|
||||||
import { computeNavigation } from "./navigation";
|
import { computeNavigation } from "./navigation";
|
||||||
import type { Subscription } from "@customer-portal/domain";
|
import type { Subscription } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface AppShellProps {
|
interface AppShellProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import type { Subscription } from "@customer-portal/domain";
|
import type { Subscription } from "@customer-portal/domain/billing";
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import {
|
import {
|
||||||
HomeIcon,
|
HomeIcon,
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import { SubCard } from "@/components/molecules/SubCard/SubCard";
|
import { SubCard } from "@/components/molecules/SubCard/SubCard";
|
||||||
import { MapPinIcon, PencilIcon, CheckIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
import { MapPinIcon, PencilIcon, CheckIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||||
import { AddressForm, type AddressFormProps } from "@/features/catalog/components";
|
import { AddressForm, type AddressFormProps } from "@/features/catalog/components";
|
||||||
import type { Address } from "@customer-portal/domain";
|
import type { Address } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface AddressCardProps {
|
interface AddressCardProps {
|
||||||
address: Address;
|
address: Address;
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { SubCard } from "@/components/molecules/SubCard/SubCard";
|
import { SubCard } from "@/components/molecules/SubCard/SubCard";
|
||||||
import { UserIcon, PencilIcon, CheckIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
import { UserIcon, PencilIcon, CheckIcon, XMarkIcon } from "@heroicons/react/24/outline";
|
||||||
import type { ProfileDisplayData } from "@customer-portal/domain";
|
import type { ProfileDisplayData } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface PersonalInfoCardProps {
|
interface PersonalInfoCardProps {
|
||||||
data: ProfileDisplayData;
|
data: ProfileDisplayData;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import {
|
|||||||
addressFormSchema,
|
addressFormSchema,
|
||||||
addressFormToRequest,
|
addressFormToRequest,
|
||||||
type AddressFormData,
|
type AddressFormData,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import { useZodForm } from "@customer-portal/validation";
|
import { useZodForm } from "@customer-portal/validation";
|
||||||
|
|
||||||
export function useAddressEdit(initial: AddressFormData) {
|
export function useAddressEdit(initial: AddressFormData) {
|
||||||
|
|||||||
@ -6,10 +6,10 @@ import { accountService } from "@/features/account/services/account.service";
|
|||||||
import { logger } from "@customer-portal/logging";
|
import { logger } from "@customer-portal/logging";
|
||||||
|
|
||||||
// Use centralized profile types
|
// Use centralized profile types
|
||||||
import type { ProfileEditFormData } from "@customer-portal/domain";
|
import type { ProfileEditFormData } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
// Address type moved to domain package
|
// Address type moved to domain package
|
||||||
import type { Address } from "@customer-portal/domain";
|
import type { Address } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
export function useProfileData() {
|
export function useProfileData() {
|
||||||
const { user } = useAuthStore();
|
const { user } = useAuthStore();
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import {
|
|||||||
profileEditFormSchema,
|
profileEditFormSchema,
|
||||||
profileFormToRequest,
|
profileFormToRequest,
|
||||||
type ProfileEditFormData,
|
type ProfileEditFormData,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import { useZodForm } from "@customer-portal/validation";
|
import { useZodForm } from "@customer-portal/validation";
|
||||||
|
|
||||||
export function useProfileEdit(initial: ProfileEditFormData) {
|
export function useProfileEdit(initial: ProfileEditFormData) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { apiClient, getDataOrThrow, getNullableData } from "@/lib/api";
|
import { apiClient, getDataOrThrow, getNullableData } from "@/lib/api";
|
||||||
import type { Address, UserProfile } from "@customer-portal/domain";
|
import type { Address, UserProfile } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
type ProfileUpdateInput = {
|
type ProfileUpdateInput = {
|
||||||
firstName?: string;
|
firstName?: string;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import Link from "next/link";
|
|||||||
import { Button, Input, ErrorMessage } from "@/components/atoms";
|
import { Button, Input, ErrorMessage } from "@/components/atoms";
|
||||||
import { FormField } from "@/components/molecules/FormField/FormField";
|
import { FormField } from "@/components/molecules/FormField/FormField";
|
||||||
import { useLogin } from "../../hooks/use-auth";
|
import { useLogin } from "../../hooks/use-auth";
|
||||||
import { loginFormSchema, loginFormToRequest } from "@customer-portal/domain";
|
import { loginFormSchema, loginFormToRequest } from "@customer-portal/domain/billing";
|
||||||
import { useZodForm } from "@customer-portal/validation";
|
import { useZodForm } from "@customer-portal/validation";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import {
|
|||||||
passwordResetFormSchema,
|
passwordResetFormSchema,
|
||||||
type PasswordResetRequestFormData,
|
type PasswordResetRequestFormData,
|
||||||
type PasswordResetFormData,
|
type PasswordResetFormData,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
interface PasswordResetFormProps {
|
interface PasswordResetFormProps {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { Button, Input, ErrorMessage } from "@/components/atoms";
|
|||||||
import { FormField } from "@/components/molecules/FormField/FormField";
|
import { FormField } from "@/components/molecules/FormField/FormField";
|
||||||
import { useWhmcsLink } from "../../hooks/use-auth";
|
import { useWhmcsLink } from "../../hooks/use-auth";
|
||||||
import { useZodForm } from "@customer-portal/validation";
|
import { useZodForm } from "@customer-portal/validation";
|
||||||
import { setPasswordFormSchema, type SetPasswordFormData } from "@customer-portal/domain";
|
import { setPasswordFormSchema, type SetPasswordFormData } from "@customer-portal/domain/billing";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
interface SetPasswordFormProps {
|
interface SetPasswordFormProps {
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import {
|
|||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { StatusPill } from "@/components/atoms/status-pill";
|
import { StatusPill } from "@/components/atoms/status-pill";
|
||||||
import type { StatusPillProps } from "@/components/atoms/status-pill";
|
import type { StatusPillProps } from "@/components/atoms/status-pill";
|
||||||
import type { InvoiceStatus } from "@customer-portal/domain";
|
import type { InvoiceStatus } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface BillingStatusBadgeProps extends Omit<StatusPillProps, "variant" | "icon" | "label"> {
|
interface BillingStatusBadgeProps extends Omit<StatusPillProps, "variant" | "icon" | "label"> {
|
||||||
status: string;
|
status: string;
|
||||||
|
|||||||
@ -10,8 +10,8 @@ import {
|
|||||||
ArrowRightIcon,
|
ArrowRightIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { BillingStatusBadge } from "../BillingStatusBadge";
|
import { BillingStatusBadge } from "../BillingStatusBadge";
|
||||||
import type { BillingSummaryData } from "@customer-portal/domain";
|
import type { BillingSummaryData } from "@customer-portal/domain/billing";
|
||||||
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain";
|
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain/billing";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
interface BillingSummaryProps extends React.HTMLAttributes<HTMLDivElement> {
|
interface BillingSummaryProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
|
|||||||
@ -8,8 +8,8 @@ import {
|
|||||||
ServerIcon,
|
ServerIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import type { Invoice } from "@customer-portal/domain";
|
import type { Invoice } from "@customer-portal/domain/billing";
|
||||||
import { formatCurrency } from "@customer-portal/domain";
|
import { formatCurrency } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
const formatDate = (dateString?: string) => {
|
const formatDate = (dateString?: string) => {
|
||||||
if (!dateString || dateString === "0000-00-00" || dateString === "0000-00-00 00:00:00")
|
if (!dateString || dateString === "0000-00-00" || dateString === "0000-00-00 00:00:00")
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { formatCurrency } from "@customer-portal/domain";
|
import { formatCurrency } from "@customer-portal/domain/billing";
|
||||||
import type { InvoiceItem } from "@customer-portal/domain";
|
import type { InvoiceItem } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface InvoiceItemsProps {
|
interface InvoiceItemsProps {
|
||||||
items?: InvoiceItem[];
|
items?: InvoiceItem[];
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { format, formatDistanceToNowStrict } from "date-fns";
|
import { format, formatDistanceToNowStrict } from "date-fns";
|
||||||
import { ArrowDownTrayIcon, ArrowTopRightOnSquareIcon } from "@heroicons/react/24/outline";
|
import { ArrowDownTrayIcon, ArrowTopRightOnSquareIcon } from "@heroicons/react/24/outline";
|
||||||
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain";
|
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain/billing";
|
||||||
import type { Invoice } from "@customer-portal/domain";
|
import type { Invoice } from "@customer-portal/domain/billing";
|
||||||
import { Button } from "@/components/atoms/button";
|
import { Button } from "@/components/atoms/button";
|
||||||
import { StatusPill } from "@/components/atoms/status-pill";
|
import { StatusPill } from "@/components/atoms/status-pill";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { formatCurrency } from "@customer-portal/domain";
|
import { formatCurrency } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface InvoiceTotalsProps {
|
interface InvoiceTotalsProps {
|
||||||
subtotal: number;
|
subtotal: number;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { formatCurrency } from "@customer-portal/domain";
|
import { formatCurrency } from "@customer-portal/domain/billing";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
export function InvoiceItemRow({
|
export function InvoiceItemRow({
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { PaginationBar } from "@/components/molecules/PaginationBar/PaginationBa
|
|||||||
import { InvoiceTable } from "@/features/billing/components/InvoiceTable/InvoiceTable";
|
import { InvoiceTable } from "@/features/billing/components/InvoiceTable/InvoiceTable";
|
||||||
import { useInvoices } from "@/features/billing/hooks/useBilling";
|
import { useInvoices } from "@/features/billing/hooks/useBilling";
|
||||||
import { useSubscriptionInvoices } from "@/features/subscriptions/hooks/useSubscriptions";
|
import { useSubscriptionInvoices } from "@/features/subscriptions/hooks/useSubscriptions";
|
||||||
import type { Invoice } from "@customer-portal/domain";
|
import type { Invoice } from "@customer-portal/domain/billing";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
interface InvoicesListProps {
|
interface InvoicesListProps {
|
||||||
|
|||||||
@ -16,8 +16,8 @@ import { CheckCircleIcon as CheckCircleIconSolid } from "@heroicons/react/24/sol
|
|||||||
import { DataTable } from "@/components/molecules/DataTable/DataTable";
|
import { DataTable } from "@/components/molecules/DataTable/DataTable";
|
||||||
import { Button } from "@/components/atoms/button";
|
import { Button } from "@/components/atoms/button";
|
||||||
import { BillingStatusBadge } from "../BillingStatusBadge";
|
import { BillingStatusBadge } from "../BillingStatusBadge";
|
||||||
import type { Invoice } from "@customer-portal/domain";
|
import type { Invoice } from "@customer-portal/domain/billing";
|
||||||
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain";
|
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain/billing";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { useCreateInvoiceSsoLink } from "@/features/billing/hooks/useBilling";
|
import { useCreateInvoiceSsoLink } from "@/features/billing/hooks/useBilling";
|
||||||
import { openSsoLink } from "@/features/billing/utils/sso";
|
import { openSsoLink } from "@/features/billing/utils/sso";
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { CreditCardIcon, BanknotesIcon, DevicePhoneMobileIcon, CheckCircleIcon } from "@heroicons/react/24/outline";
|
import { CreditCardIcon, BanknotesIcon, DevicePhoneMobileIcon, CheckCircleIcon } from "@heroicons/react/24/outline";
|
||||||
import type { PaymentMethod } from "@customer-portal/domain";
|
import type { PaymentMethod } from "@customer-portal/domain/billing";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import {
|
|||||||
ArrowPathIcon,
|
ArrowPathIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { Badge } from "@/components/atoms/badge";
|
import { Badge } from "@/components/atoms/badge";
|
||||||
import type { PaymentMethod } from "@customer-portal/domain";
|
import type { PaymentMethod } from "@customer-portal/domain/billing";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
interface PaymentMethodCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
interface PaymentMethodCardProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
|
|||||||
@ -16,12 +16,12 @@ import type {
|
|||||||
InvoiceList,
|
InvoiceList,
|
||||||
InvoiceSsoLink,
|
InvoiceSsoLink,
|
||||||
PaymentMethodList,
|
PaymentMethodList,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import {
|
import {
|
||||||
invoiceListSchema,
|
invoiceListSchema,
|
||||||
invoiceSchema as sharedInvoiceSchema,
|
invoiceSchema as sharedInvoiceSchema,
|
||||||
} from "@customer-portal/domain/validation/shared/entities";
|
} from "@customer-portal/domain/validation/shared/entities";
|
||||||
import { INVOICE_STATUS } from "@customer-portal/domain";
|
import { INVOICE_STATUS } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
const emptyInvoiceList: InvoiceList = {
|
const emptyInvoiceList: InvoiceList = {
|
||||||
invoices: [],
|
invoices: [],
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { logger } from "@customer-portal/logging";
|
|||||||
import { apiClient, getDataOrThrow } from "@/lib/api";
|
import { apiClient, getDataOrThrow } from "@/lib/api";
|
||||||
import { openSsoLink } from "@/features/billing/utils/sso";
|
import { openSsoLink } from "@/features/billing/utils/sso";
|
||||||
import { useInvoice, useCreateInvoiceSsoLink } from "@/features/billing/hooks";
|
import { useInvoice, useCreateInvoiceSsoLink } from "@/features/billing/hooks";
|
||||||
import type { InvoiceSsoLink } from "@customer-portal/domain";
|
import type { InvoiceSsoLink } from "@customer-portal/domain/billing";
|
||||||
import {
|
import {
|
||||||
InvoiceItems,
|
InvoiceItems,
|
||||||
InvoiceTotals,
|
InvoiceTotals,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { CheckCircleIcon } from "@heroicons/react/24/solid";
|
import { CheckCircleIcon } from "@heroicons/react/24/solid";
|
||||||
import type { CatalogProductBase } from "@customer-portal/domain";
|
import type { CatalogProductBase } from "@customer-portal/domain/billing";
|
||||||
import { getMonthlyPrice, getOneTimePrice } from "../../utils/pricing";
|
import { getMonthlyPrice, getOneTimePrice } from "../../utils/pricing";
|
||||||
|
|
||||||
interface AddonGroupProps {
|
interface AddonGroupProps {
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import {
|
|||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
|
|
||||||
// Use canonical Address type from domain
|
// Use canonical Address type from domain
|
||||||
import type { Address } from "@customer-portal/domain";
|
import type { Address } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface BillingInfo {
|
interface BillingInfo {
|
||||||
company: string | null;
|
company: string | null;
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { MapPinIcon, ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
import { MapPinIcon, ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||||
import { useZodForm } from "@customer-portal/validation";
|
import { useZodForm } from "@customer-portal/validation";
|
||||||
import { addressFormSchema, type AddressFormData, type Address } from "@customer-portal/domain";
|
import { addressFormSchema, type AddressFormData, type Address } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
export interface AddressFormProps {
|
export interface AddressFormProps {
|
||||||
// Initial values
|
// Initial values
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { Button } from "@/components/atoms/button";
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
// Align with shared catalog contracts
|
// Align with shared catalog contracts
|
||||||
import type { CatalogProductBase } from "@customer-portal/domain";
|
import type { CatalogProductBase } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
// Enhanced order item representation for UI summary
|
// Enhanced order item representation for UI summary
|
||||||
export type OrderItem = CatalogProductBase & {
|
export type OrderItem = CatalogProductBase & {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/react/24/outline";
|
import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/react/24/outline";
|
||||||
import type { CatalogProductBase } from "@customer-portal/domain";
|
import type { CatalogProductBase } from "@customer-portal/domain/billing";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { Button } from "@/components/atoms/button";
|
import { Button } from "@/components/atoms/button";
|
||||||
import { getMonthlyPrice, getOneTimePrice } from "../../utils/pricing";
|
import { getMonthlyPrice, getOneTimePrice } from "../../utils/pricing";
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { Skeleton } from "@/components/atoms/loading-skeleton";
|
|||||||
import { Button } from "@/components/atoms/button";
|
import { Button } from "@/components/atoms/button";
|
||||||
import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner";
|
import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner";
|
||||||
import { CreditCardIcon, CheckCircleIcon } from "@heroicons/react/24/outline";
|
import { CreditCardIcon, CheckCircleIcon } from "@heroicons/react/24/outline";
|
||||||
import type { PaymentMethod } from "@customer-portal/domain";
|
import type { PaymentMethod } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
export interface PaymentFormProps {
|
export interface PaymentFormProps {
|
||||||
existingMethods?: PaymentMethod[];
|
existingMethods?: PaymentMethod[];
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import type { InternetInstallationCatalogItem } from "@customer-portal/domain";
|
import type { InternetInstallationCatalogItem } from "@customer-portal/domain/billing";
|
||||||
import { getDisplayPrice } from "../../utils/pricing";
|
import { getDisplayPrice } from "../../utils/pricing";
|
||||||
import {
|
import {
|
||||||
inferInstallationTypeFromSku,
|
inferInstallationTypeFromSku,
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import type {
|
|||||||
InternetPlanCatalogItem,
|
InternetPlanCatalogItem,
|
||||||
InternetInstallationCatalogItem,
|
InternetInstallationCatalogItem,
|
||||||
InternetAddonCatalogItem,
|
InternetAddonCatalogItem,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
plan: InternetPlanCatalogItem | null;
|
plan: InternetPlanCatalogItem | null;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { CurrencyYenIcon, ArrowRightIcon } from "@heroicons/react/24/outline";
|
|||||||
import type {
|
import type {
|
||||||
InternetPlanCatalogItem,
|
InternetPlanCatalogItem,
|
||||||
InternetInstallationCatalogItem,
|
InternetInstallationCatalogItem,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { getMonthlyPrice, getOneTimePrice } from "../../utils/pricing";
|
import { getMonthlyPrice, getOneTimePrice } from "../../utils/pricing";
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import type {
|
|||||||
InternetPlanCatalogItem,
|
InternetPlanCatalogItem,
|
||||||
InternetInstallationCatalogItem,
|
InternetInstallationCatalogItem,
|
||||||
InternetAddonCatalogItem,
|
InternetAddonCatalogItem,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import { ConfigureLoadingSkeleton } from "./components/ConfigureLoadingSkeleton";
|
import { ConfigureLoadingSkeleton } from "./components/ConfigureLoadingSkeleton";
|
||||||
import { ServiceConfigurationStep } from "./steps/ServiceConfigurationStep";
|
import { ServiceConfigurationStep } from "./steps/ServiceConfigurationStep";
|
||||||
import { InstallationStep } from "./steps/InstallationStep";
|
import { InstallationStep } from "./steps/InstallationStep";
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import type {
|
|||||||
InternetPlanCatalogItem,
|
InternetPlanCatalogItem,
|
||||||
InternetInstallationCatalogItem,
|
InternetInstallationCatalogItem,
|
||||||
InternetAddonCatalogItem,
|
InternetAddonCatalogItem,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import type { AccessMode } from "../../../../hooks/useConfigureParams";
|
import type { AccessMode } from "../../../../hooks/useConfigureParams";
|
||||||
import { getMonthlyPrice, getOneTimePrice } from "../../../../utils/pricing";
|
import { getMonthlyPrice, getOneTimePrice } from "../../../../utils/pricing";
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { Button } from "@/components/atoms/button";
|
|||||||
import { StepHeader } from "@/components/atoms";
|
import { StepHeader } from "@/components/atoms";
|
||||||
import { AddonGroup } from "@/features/catalog/components/base/AddonGroup";
|
import { AddonGroup } from "@/features/catalog/components/base/AddonGroup";
|
||||||
import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/react/24/outline";
|
import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/react/24/outline";
|
||||||
import type { InternetAddonCatalogItem } from "@customer-portal/domain";
|
import type { InternetAddonCatalogItem } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
addons: InternetAddonCatalogItem[];
|
addons: InternetAddonCatalogItem[];
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { Button } from "@/components/atoms/button";
|
|||||||
import { StepHeader } from "@/components/atoms";
|
import { StepHeader } from "@/components/atoms";
|
||||||
import { InstallationOptions } from "../../InstallationOptions";
|
import { InstallationOptions } from "../../InstallationOptions";
|
||||||
import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/react/24/outline";
|
import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/react/24/outline";
|
||||||
import type { InternetInstallationCatalogItem } from "@customer-portal/domain";
|
import type { InternetInstallationCatalogItem } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
installations: InternetInstallationCatalogItem[];
|
installations: InternetInstallationCatalogItem[];
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import type {
|
|||||||
InternetPlanCatalogItem,
|
InternetPlanCatalogItem,
|
||||||
InternetInstallationCatalogItem,
|
InternetInstallationCatalogItem,
|
||||||
InternetAddonCatalogItem,
|
InternetAddonCatalogItem,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import type { AccessMode } from "../../../../hooks/useConfigureParams";
|
import type { AccessMode } from "../../../../hooks/useConfigureParams";
|
||||||
import { getMonthlyPrice, getOneTimePrice } from "../../../../utils/pricing";
|
import { getMonthlyPrice, getOneTimePrice } from "../../../../utils/pricing";
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { Button } from "@/components/atoms/button";
|
|||||||
import { StepHeader } from "@/components/atoms";
|
import { StepHeader } from "@/components/atoms";
|
||||||
import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner";
|
import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner";
|
||||||
import { ArrowRightIcon } from "@heroicons/react/24/outline";
|
import { ArrowRightIcon } from "@heroicons/react/24/outline";
|
||||||
import type { InternetPlanCatalogItem } from "@customer-portal/domain";
|
import type { InternetPlanCatalogItem } from "@customer-portal/domain/billing";
|
||||||
import type { AccessMode } from "../../../../hooks/useConfigureParams";
|
import type { AccessMode } from "../../../../hooks/useConfigureParams";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import { DevicePhoneMobileIcon, UsersIcon, CurrencyYenIcon } from "@heroicons/react/24/outline";
|
import { DevicePhoneMobileIcon, UsersIcon, CurrencyYenIcon } from "@heroicons/react/24/outline";
|
||||||
import { AnimatedCard } from "@/components/molecules/AnimatedCard/AnimatedCard";
|
import { AnimatedCard } from "@/components/molecules/AnimatedCard/AnimatedCard";
|
||||||
import { Button } from "@/components/atoms/button";
|
import { Button } from "@/components/atoms/button";
|
||||||
import type { SimCatalogProduct } from "@customer-portal/domain";
|
import type { SimCatalogProduct } from "@customer-portal/domain/billing";
|
||||||
import { getMonthlyPrice } from "../../utils/pricing";
|
import { getMonthlyPrice } from "../../utils/pricing";
|
||||||
|
|
||||||
interface SimPlanCardProps {
|
interface SimPlanCardProps {
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { UsersIcon } from "@heroicons/react/24/outline";
|
import { UsersIcon } from "@heroicons/react/24/outline";
|
||||||
import type { SimCatalogProduct } from "@customer-portal/domain";
|
import type { SimCatalogProduct } from "@customer-portal/domain/billing";
|
||||||
import { SimPlanCard } from "./SimPlanCard";
|
import { SimPlanCard } from "./SimPlanCard";
|
||||||
|
|
||||||
interface SimPlanTypeSectionProps {
|
interface SimPlanTypeSectionProps {
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import { AnimatedCard } from "@/components/molecules";
|
import { AnimatedCard } from "@/components/molecules";
|
||||||
import { Button } from "@/components/atoms/button";
|
import { Button } from "@/components/atoms/button";
|
||||||
import { CurrencyYenIcon } from "@heroicons/react/24/outline";
|
import { CurrencyYenIcon } from "@heroicons/react/24/outline";
|
||||||
import type { VpnCatalogProduct } from "@customer-portal/domain";
|
import type { VpnCatalogProduct } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface VpnPlanCardProps {
|
interface VpnPlanCardProps {
|
||||||
plan: VpnCatalogProduct;
|
plan: VpnCatalogProduct;
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import type {
|
|||||||
InternetPlanCatalogItem,
|
InternetPlanCatalogItem,
|
||||||
InternetInstallationCatalogItem,
|
InternetInstallationCatalogItem,
|
||||||
InternetAddonCatalogItem,
|
InternetAddonCatalogItem,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import { inferInstallationTypeFromSku } from "../utils/inferInstallationType";
|
import { inferInstallationTypeFromSku } from "../utils/inferInstallationType";
|
||||||
import { getMonthlyPrice, getOneTimePrice } from "../utils/pricing";
|
import { getMonthlyPrice, getOneTimePrice } from "../utils/pricing";
|
||||||
|
|
||||||
|
|||||||
@ -11,8 +11,8 @@ import {
|
|||||||
type SimType,
|
type SimType,
|
||||||
type ActivationType,
|
type ActivationType,
|
||||||
type MnpData,
|
type MnpData,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import type { SimCatalogProduct, SimActivationFeeCatalogItem } from "@customer-portal/domain";
|
import type { SimCatalogProduct, SimActivationFeeCatalogItem } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
export type UseSimConfigureResult = {
|
export type UseSimConfigureResult = {
|
||||||
// data
|
// data
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export * from "./hooks";
|
|||||||
// Services
|
// Services
|
||||||
export * from "./services";
|
export * from "./services";
|
||||||
|
|
||||||
// Import domain types directly: import type { Address } from "@customer-portal/domain";
|
// Import domain types directly: import type { Address } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
export * from "./utils";
|
export * from "./utils";
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import type {
|
|||||||
SimCatalogProduct,
|
SimCatalogProduct,
|
||||||
SimActivationFeeCatalogItem,
|
SimActivationFeeCatalogItem,
|
||||||
VpnCatalogProduct,
|
VpnCatalogProduct,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
const emptyInternetPlans: InternetPlanCatalogItem[] = [];
|
const emptyInternetPlans: InternetPlanCatalogItem[] = [];
|
||||||
const emptyInternetAddons: InternetAddonCatalogItem[] = [];
|
const emptyInternetAddons: InternetAddonCatalogItem[] = [];
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
* Helper functions for catalog operations
|
* Helper functions for catalog operations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { formatCurrency } from "@customer-portal/domain";
|
import { formatCurrency } from "@customer-portal/domain/billing";
|
||||||
import type {
|
import type {
|
||||||
CatalogFilter,
|
CatalogFilter,
|
||||||
InternetPlanCatalogItem,
|
InternetPlanCatalogItem,
|
||||||
@ -11,7 +11,7 @@ import type {
|
|||||||
InternetInstallationCatalogItem,
|
InternetInstallationCatalogItem,
|
||||||
SimCatalogProduct,
|
SimCatalogProduct,
|
||||||
VpnCatalogProduct,
|
VpnCatalogProduct,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
type CatalogProduct =
|
type CatalogProduct =
|
||||||
| InternetPlanCatalogItem
|
| InternetPlanCatalogItem
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import type { CatalogProductBase } from "@customer-portal/domain";
|
import type { CatalogProductBase } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
export function getMonthlyPrice(product?: CatalogProductBase | null): number {
|
export function getMonthlyPrice(product?: CatalogProductBase | null): number {
|
||||||
if (!product) return 0;
|
if (!product) return 0;
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import type {
|
|||||||
InternetPlanCatalogItem,
|
InternetPlanCatalogItem,
|
||||||
InternetInstallationCatalogItem,
|
InternetInstallationCatalogItem,
|
||||||
InternetAddonCatalogItem,
|
InternetAddonCatalogItem,
|
||||||
} from "@customer-portal/domain";
|
} from "@customer-portal/domain/billing";
|
||||||
import { getMonthlyPrice } from "../utils/pricing";
|
import { getMonthlyPrice } from "../utils/pricing";
|
||||||
import { LoadingCard, Skeleton, LoadingTable } from "@/components/atoms/loading-skeleton";
|
import { LoadingCard, Skeleton, LoadingTable } from "@/components/atoms/loading-skeleton";
|
||||||
import { AnimatedCard } from "@/components/molecules";
|
import { AnimatedCard } from "@/components/molecules";
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import { LoadingCard, Skeleton } from "@/components/atoms/loading-skeleton";
|
|||||||
import { Button } from "@/components/atoms/button";
|
import { Button } from "@/components/atoms/button";
|
||||||
import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner";
|
import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner";
|
||||||
import { useSimCatalog } from "@/features/catalog/hooks";
|
import { useSimCatalog } from "@/features/catalog/hooks";
|
||||||
import type { SimCatalogProduct } from "@customer-portal/domain";
|
import type { SimCatalogProduct } from "@customer-portal/domain/billing";
|
||||||
import { SimPlanTypeSection } from "@/features/catalog/components/sim/SimPlanTypeSection";
|
import { SimPlanTypeSection } from "@/features/catalog/components/sim/SimPlanTypeSection";
|
||||||
|
|
||||||
interface PlansByType {
|
interface PlansByType {
|
||||||
|
|||||||
@ -7,13 +7,13 @@ import { ordersService } from "@/features/orders/services/orders.service";
|
|||||||
import { usePaymentMethods } from "@/features/billing/hooks/useBilling";
|
import { usePaymentMethods } from "@/features/billing/hooks/useBilling";
|
||||||
import { usePaymentRefresh } from "@/features/billing/hooks/usePaymentRefresh";
|
import { usePaymentRefresh } from "@/features/billing/hooks/usePaymentRefresh";
|
||||||
import { getMonthlyPrice, getOneTimePrice } from "@/features/catalog/utils/pricing";
|
import { getMonthlyPrice, getOneTimePrice } from "@/features/catalog/utils/pricing";
|
||||||
import type { CatalogProductBase } from "@customer-portal/domain";
|
import type { CatalogProductBase } from "@customer-portal/domain/billing";
|
||||||
import { createLoadingState, createSuccessState, createErrorState } from "@customer-portal/domain";
|
import { createLoadingState, createSuccessState, createErrorState } from "@customer-portal/domain/billing";
|
||||||
import type { AsyncState } from "@customer-portal/domain";
|
import type { AsyncState } from "@customer-portal/domain/billing";
|
||||||
import { useActiveSubscriptions } from "@/features/subscriptions/hooks/useSubscriptions";
|
import { useActiveSubscriptions } from "@/features/subscriptions/hooks/useSubscriptions";
|
||||||
|
|
||||||
// Use domain Address type
|
// Use domain Address type
|
||||||
import type { Address } from "@customer-portal/domain";
|
import type { Address } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
type CheckoutItemType = "plan" | "installation" | "addon" | "activation" | "vpn";
|
type CheckoutItemType = "plan" | "installation" | "addon" | "activation" | "vpn";
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { PageAsync } from "@/components/molecules/AsyncBlock/AsyncBlock";
|
|||||||
import { InlineToast } from "@/components/atoms/inline-toast";
|
import { InlineToast } from "@/components/atoms/inline-toast";
|
||||||
import { StatusPill } from "@/components/atoms/status-pill";
|
import { StatusPill } from "@/components/atoms/status-pill";
|
||||||
import { AddressConfirmation } from "@/features/catalog/components/base/AddressConfirmation";
|
import { AddressConfirmation } from "@/features/catalog/components/base/AddressConfirmation";
|
||||||
import { isLoading, isError, isSuccess } from "@customer-portal/domain";
|
import { isLoading, isError, isSuccess } from "@customer-portal/domain/billing";
|
||||||
import {
|
import {
|
||||||
ExclamationTriangleIcon,
|
ExclamationTriangleIcon,
|
||||||
ShieldCheckIcon,
|
ShieldCheckIcon,
|
||||||
|
|||||||
@ -10,8 +10,8 @@ import {
|
|||||||
getActivityNavigationPath,
|
getActivityNavigationPath,
|
||||||
isActivityClickable,
|
isActivityClickable,
|
||||||
} from "../utils/dashboard.utils";
|
} from "../utils/dashboard.utils";
|
||||||
import type { Activity } from "@customer-portal/domain";
|
import type { Activity } from "@customer-portal/domain/billing";
|
||||||
import type { ActivityFilter } from "@customer-portal/domain";
|
import type { ActivityFilter } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
export interface ActivityFeedProps {
|
export interface ActivityFeedProps {
|
||||||
activities: Activity[];
|
activities: Activity[];
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { CalendarDaysIcon, ChevronRightIcon } from "@heroicons/react/24/outline";
|
import { CalendarDaysIcon, ChevronRightIcon } from "@heroicons/react/24/outline";
|
||||||
import { format, formatDistanceToNow } from "date-fns";
|
import { format, formatDistanceToNow } from "date-fns";
|
||||||
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain";
|
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface UpcomingPaymentBannerProps {
|
interface UpcomingPaymentBannerProps {
|
||||||
invoice: { id: number; amount: number; currency?: string; dueDate: string };
|
invoice: { id: number; amount: number; currency?: string; dueDate: string };
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { useAuthSession } from "@/features/auth/services/auth.store";
|
import { useAuthSession } from "@/features/auth/services/auth.store";
|
||||||
import { apiClient, queryKeys, getDataOrThrow } from "@/lib/api";
|
import { apiClient, queryKeys, getDataOrThrow } from "@/lib/api";
|
||||||
import type { DashboardSummary, DashboardError } from "@customer-portal/domain";
|
import type { DashboardSummary, DashboardError } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
class DashboardDataError extends Error {
|
class DashboardDataError extends Error {
|
||||||
constructor(
|
constructor(
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
* Helper functions for dashboard data processing and formatting
|
* Helper functions for dashboard data processing and formatting
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Activity } from "@customer-portal/domain";
|
import type { Activity } from "@customer-portal/domain/billing";
|
||||||
import type { ActivityFilter, ActivityFilterConfig } from "@customer-portal/domain";
|
import type { ActivityFilter, ActivityFilterConfig } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activity filter configurations
|
* Activity filter configurations
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import type { Activity, DashboardSummary } from "@customer-portal/domain";
|
import type { Activity, DashboardSummary } from "@customer-portal/domain/billing";
|
||||||
import {
|
import {
|
||||||
ServerIcon,
|
ServerIcon,
|
||||||
ChatBubbleLeftRightIcon,
|
ChatBubbleLeftRightIcon,
|
||||||
@ -25,7 +25,7 @@ import { useDashboardSummary } from "@/features/dashboard/hooks";
|
|||||||
import { StatCard, QuickAction, DashboardActivityItem } from "@/features/dashboard/components";
|
import { StatCard, QuickAction, DashboardActivityItem } from "@/features/dashboard/components";
|
||||||
import { LoadingStats, LoadingTable } from "@/components/atoms";
|
import { LoadingStats, LoadingTable } from "@/components/atoms";
|
||||||
import { ErrorState } from "@/components/atoms/error-state";
|
import { ErrorState } from "@/components/atoms/error-state";
|
||||||
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain";
|
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain/billing";
|
||||||
import { log } from "@customer-portal/logging";
|
import { log } from "@customer-portal/logging";
|
||||||
import { useCreateInvoiceSsoLink } from "@/features/billing/hooks/useBilling";
|
import { useCreateInvoiceSsoLink } from "@/features/billing/hooks/useBilling";
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { apiClient } from "@/lib/api";
|
import { apiClient } from "@/lib/api";
|
||||||
import type { CreateOrderRequest } from "@customer-portal/domain";
|
import type { CreateOrderRequest } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
async function createOrder<T = { sfOrderId: string }>(payload: CreateOrderRequest): Promise<T> {
|
async function createOrder<T = { sfOrderId: string }>(payload: CreateOrderRequest): Promise<T> {
|
||||||
const response = await apiClient.POST("/api/orders", { body: payload });
|
const response = await apiClient.POST("/api/orders", { body: payload });
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import {
|
|||||||
ExclamationTriangleIcon,
|
ExclamationTriangleIcon,
|
||||||
XCircleIcon,
|
XCircleIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import type { SimDetails } from "@customer-portal/contracts/sim";
|
import type { SimDetails } from "@customer-portal/domain/sim";
|
||||||
|
|
||||||
interface SimDetailsCardProps {
|
interface SimDetailsCardProps {
|
||||||
simDetails: SimDetails;
|
simDetails: SimDetails;
|
||||||
|
|||||||
@ -15,8 +15,8 @@ import {
|
|||||||
import { StatusPill } from "@/components/atoms/status-pill";
|
import { StatusPill } from "@/components/atoms/status-pill";
|
||||||
import { Button } from "@/components/atoms/button";
|
import { Button } from "@/components/atoms/button";
|
||||||
import { SubCard } from "@/components/molecules/SubCard/SubCard";
|
import { SubCard } from "@/components/molecules/SubCard/SubCard";
|
||||||
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain";
|
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain/billing";
|
||||||
import type { Subscription } from "@customer-portal/domain";
|
import type { Subscription } from "@customer-portal/domain/billing";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
interface SubscriptionCardProps {
|
interface SubscriptionCardProps {
|
||||||
|
|||||||
@ -15,8 +15,8 @@ import {
|
|||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { StatusPill } from "@/components/atoms/status-pill";
|
import { StatusPill } from "@/components/atoms/status-pill";
|
||||||
import { SubCard } from "@/components/molecules/SubCard/SubCard";
|
import { SubCard } from "@/components/molecules/SubCard/SubCard";
|
||||||
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain";
|
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain/billing";
|
||||||
import type { Subscription } from "@customer-portal/domain";
|
import type { Subscription } from "@customer-portal/domain/billing";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
interface SubscriptionDetailsProps {
|
interface SubscriptionDetailsProps {
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { apiClient, queryKeys, getDataOrDefault, getDataOrThrow, getNullableData } from "@/lib/api";
|
import { apiClient, queryKeys, getDataOrDefault, getDataOrThrow, getNullableData } from "@/lib/api";
|
||||||
import { useAuthSession } from "@/features/auth/services";
|
import { useAuthSession } from "@/features/auth/services";
|
||||||
import type { InvoiceList, Subscription, SubscriptionList } from "@customer-portal/domain";
|
import type { InvoiceList, Subscription, SubscriptionList } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
interface UseSubscriptionsOptions {
|
interface UseSubscriptionsOptions {
|
||||||
status?: string;
|
status?: string;
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import {
|
|||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import { useSubscription } from "@/features/subscriptions/hooks";
|
import { useSubscription } from "@/features/subscriptions/hooks";
|
||||||
import { InvoicesList } from "@/features/billing/components/InvoiceList/InvoiceList";
|
import { InvoicesList } from "@/features/billing/components/InvoiceList/InvoiceList";
|
||||||
import { formatCurrency as sharedFormatCurrency, getCurrencyLocale } from "@customer-portal/domain";
|
import { formatCurrency as sharedFormatCurrency, getCurrencyLocale } from "@customer-portal/domain/billing";
|
||||||
import { SimManagementSection } from "@/features/sim-management";
|
import { SimManagementSection } from "@/features/sim-management";
|
||||||
|
|
||||||
export function SubscriptionDetailContainer() {
|
export function SubscriptionDetailContainer() {
|
||||||
|
|||||||
@ -23,8 +23,8 @@ import {
|
|||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import { useSubscriptions, useSubscriptionStats } from "@/features/subscriptions/hooks";
|
import { useSubscriptions, useSubscriptionStats } from "@/features/subscriptions/hooks";
|
||||||
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain";
|
import { formatCurrency, getCurrencyLocale } from "@customer-portal/domain/billing";
|
||||||
import type { Subscription } from "@customer-portal/domain";
|
import type { Subscription } from "@customer-portal/domain/billing";
|
||||||
|
|
||||||
export function SubscriptionsListContainer() {
|
export function SubscriptionsListContainer() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|||||||
@ -91,12 +91,4 @@ export const authResponseSchema = z.object({
|
|||||||
tokens: authTokensSchema,
|
tokens: authTokensSchema,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const validateSignupRequestSchema = signupRequestSchema.pick({ sfNumber: true });
|
|
||||||
export const accountStatusRequestSchema = z.object({ email: emailSchema });
|
|
||||||
export const ssoLinkRequestSchema = z.object({ destination: z.string().optional() });
|
|
||||||
export const checkPasswordNeededRequestSchema = z.object({ email: emailSchema });
|
|
||||||
export const refreshTokenRequestSchema = z.object({
|
|
||||||
refreshToken: z.string().min(1, "Refresh token is required").optional(),
|
|
||||||
deviceId: z.string().optional(),
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,14 @@ export type CancelPlanRequest = Requests.FreebitCancelPlanRequest;
|
|||||||
export type CancelPlanApiRequest = Requests.FreebitCancelPlanApiRequest;
|
export type CancelPlanApiRequest = Requests.FreebitCancelPlanApiRequest;
|
||||||
export type CancelAccountRequest = Requests.FreebitCancelAccountRequest;
|
export type CancelAccountRequest = Requests.FreebitCancelAccountRequest;
|
||||||
export type AuthRequest = Requests.FreebitAuthRequest;
|
export type AuthRequest = Requests.FreebitAuthRequest;
|
||||||
|
export type TopUpResponse = ReturnType<typeof Mapper.transformFreebitTopUpResponse>;
|
||||||
|
export type AddSpecResponse = ReturnType<typeof Mapper.transformFreebitAddSpecResponse>;
|
||||||
|
export type PlanChangeResponse = ReturnType<typeof Mapper.transformFreebitPlanChangeResponse>;
|
||||||
|
export type CancelPlanResponse = ReturnType<typeof Mapper.transformFreebitCancelPlanResponse>;
|
||||||
|
export type CancelAccountResponse = ReturnType<typeof Mapper.transformFreebitCancelAccountResponse>;
|
||||||
|
export type EsimReissueResponse = ReturnType<typeof Mapper.transformFreebitEsimReissueResponse>;
|
||||||
|
export type EsimAddAccountResponse = ReturnType<typeof Mapper.transformFreebitEsimAddAccountResponse>;
|
||||||
|
export type EsimActivationResponse = ReturnType<typeof Mapper.transformFreebitEsimActivationResponse>;
|
||||||
|
|
||||||
export * from "./mapper";
|
export * from "./mapper";
|
||||||
export * from "./raw.types";
|
export * from "./raw.types";
|
||||||
|
|||||||
@ -125,16 +125,12 @@ export function transformFreebitTrafficInfo(raw: unknown): SimUsage {
|
|||||||
|
|
||||||
const simUsage: SimUsage = {
|
const simUsage: SimUsage = {
|
||||||
account: asString(response.account),
|
account: asString(response.account),
|
||||||
todayUsageMb: asNumber(response.todayData) / 1024,
|
todayUsageMb: response.traffic?.today ? asNumber(response.traffic.today) / 1024 : 0,
|
||||||
todayUsageKb: asNumber(response.todayData),
|
todayUsageKb: response.traffic?.today ? asNumber(response.traffic.today) : 0,
|
||||||
monthlyUsageMb: response.thisMonthData ? asNumber(response.thisMonthData) / 1024 : undefined,
|
monthlyUsageMb: undefined,
|
||||||
monthlyUsageKb: response.thisMonthData ? asNumber(response.thisMonthData) : undefined,
|
monthlyUsageKb: undefined,
|
||||||
recentDaysUsage: (response.daily || []).map(day => ({
|
recentDaysUsage: [],
|
||||||
date: day.usageDate || "",
|
isBlacklisted: parseBooleanFlag(response.traffic?.blackList),
|
||||||
usageKb: asNumber(day.trafficKb),
|
|
||||||
usageMb: asNumber(day.trafficKb) / 1024,
|
|
||||||
})),
|
|
||||||
isBlacklisted: parseBooleanFlag(response.blacklistFlg),
|
|
||||||
lastUpdated: new Date().toISOString(),
|
lastUpdated: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -146,9 +142,9 @@ export function transformFreebitQuotaHistory(raw: unknown): SimTopUpHistory {
|
|||||||
|
|
||||||
const history: SimTopUpHistory = {
|
const history: SimTopUpHistory = {
|
||||||
account: asString(response.account),
|
account: asString(response.account),
|
||||||
totalAdditions: asNumber(response.totalAddQuotaKb),
|
totalAdditions: asNumber(response.total),
|
||||||
additionCount: asNumber(response.addQuotaCount),
|
additionCount: asNumber(response.count),
|
||||||
history: (response.details || []).map(detail => ({
|
history: (response.quotaHistory || []).map(detail => ({
|
||||||
quotaKb: asNumber(detail.addQuotaKb),
|
quotaKb: asNumber(detail.addQuotaKb),
|
||||||
quotaMb: asNumber(detail.addQuotaKb) / 1024,
|
quotaMb: asNumber(detail.addQuotaKb) / 1024,
|
||||||
addedDate: detail.addDate || "",
|
addedDate: detail.addDate || "",
|
||||||
@ -168,27 +164,46 @@ export function transformFreebitTopUpResponse(raw: unknown) {
|
|||||||
return freebitTopUpRawSchema.parse(raw);
|
return freebitTopUpRawSchema.parse(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FreebitTopUpResponse = ReturnType<typeof transformFreebitTopUpResponse>;
|
||||||
|
|
||||||
export function transformFreebitAddSpecResponse(raw: unknown) {
|
export function transformFreebitAddSpecResponse(raw: unknown) {
|
||||||
return freebitAddSpecRawSchema.parse(raw);
|
return freebitAddSpecRawSchema.parse(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FreebitAddSpecResponse = ReturnType<typeof transformFreebitAddSpecResponse>;
|
||||||
|
|
||||||
export function transformFreebitPlanChangeResponse(raw: unknown) {
|
export function transformFreebitPlanChangeResponse(raw: unknown) {
|
||||||
return freebitPlanChangeRawSchema.parse(raw);
|
return freebitPlanChangeRawSchema.parse(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FreebitPlanChangeResponse = ReturnType<typeof transformFreebitPlanChangeResponse>;
|
||||||
|
|
||||||
export function transformFreebitCancelPlanResponse(raw: unknown) {
|
export function transformFreebitCancelPlanResponse(raw: unknown) {
|
||||||
return freebitCancelPlanRawSchema.parse(raw);
|
return freebitCancelPlanRawSchema.parse(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FreebitCancelPlanResponse = ReturnType<typeof transformFreebitCancelPlanResponse>;
|
||||||
|
|
||||||
export function transformFreebitCancelAccountResponse(raw: unknown) {
|
export function transformFreebitCancelAccountResponse(raw: unknown) {
|
||||||
return freebitCancelAccountRawSchema.parse(raw);
|
return freebitCancelAccountRawSchema.parse(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FreebitCancelAccountResponse = ReturnType<typeof transformFreebitCancelAccountResponse>;
|
||||||
|
|
||||||
export function transformFreebitEsimReissueResponse(raw: unknown) {
|
export function transformFreebitEsimReissueResponse(raw: unknown) {
|
||||||
return freebitEsimReissueRawSchema.parse(raw);
|
return freebitEsimReissueRawSchema.parse(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FreebitEsimReissueResponse = ReturnType<typeof transformFreebitEsimReissueResponse>;
|
||||||
|
|
||||||
export function transformFreebitEsimAddAccountResponse(raw: unknown) {
|
export function transformFreebitEsimAddAccountResponse(raw: unknown) {
|
||||||
return freebitEsimAddAccountRawSchema.parse(raw);
|
return freebitEsimAddAccountRawSchema.parse(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type FreebitEsimAddAccountResponse = ReturnType<typeof transformFreebitEsimAddAccountResponse>;
|
||||||
|
|
||||||
|
export function transformFreebitEsimActivationResponse(raw: unknown) {
|
||||||
|
return freebitEsimAddAccountRawSchema.parse(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -145,11 +145,16 @@ export type FreebitTrafficInfoRaw = z.infer<typeof freebitTrafficInfoRawSchema>;
|
|||||||
// Freebit Quota History Response
|
// Freebit Quota History Response
|
||||||
export const freebitQuotaHistoryRawSchema = z.object({
|
export const freebitQuotaHistoryRawSchema = z.object({
|
||||||
resultCode: z.string().optional(),
|
resultCode: z.string().optional(),
|
||||||
resultMessage: z.string().optional(),
|
status: z
|
||||||
|
.object({
|
||||||
|
message: z.string().optional(),
|
||||||
|
statusCode: z.union([z.string(), z.number()]).optional(),
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
account: z.union([z.string(), z.number()]).optional(),
|
account: z.union([z.string(), z.number()]).optional(),
|
||||||
totalAddQuotaKb: z.union([z.string(), z.number()]).optional(),
|
total: z.union([z.string(), z.number()]).optional(),
|
||||||
addQuotaCount: z.union([z.string(), z.number()]).optional(),
|
count: z.union([z.string(), z.number()]).optional(),
|
||||||
details: z.array(
|
quotaHistory: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
addQuotaKb: z.union([z.string(), z.number()]).optional(),
|
addQuotaKb: z.union([z.string(), z.number()]).optional(),
|
||||||
addDate: z.string().optional(),
|
addDate: z.string().optional(),
|
||||||
|
|||||||
@ -90,6 +90,37 @@ export const freebitCancelPlanApiRequestSchema = z.object({
|
|||||||
runTime: z.string().optional(),
|
runTime: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const freebitQuotaHistoryRequestSchema = z.object({
|
||||||
|
account: z.string().min(1, "Account is required"),
|
||||||
|
fromDate: z.string().regex(/^\d{8}$/, "From date must be in YYYYMMDD format"),
|
||||||
|
toDate: z.string().regex(/^\d{8}$/, "To date must be in YYYYMMDD format"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const freebitQuotaHistoryResponseSchema = z.object({
|
||||||
|
resultCode: z.string(),
|
||||||
|
status: z
|
||||||
|
.object({
|
||||||
|
message: z.string(),
|
||||||
|
statusCode: z.union([z.string(), z.number()]),
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
|
total: z.union([z.string(), z.number()]),
|
||||||
|
count: z.union([z.string(), z.number()]),
|
||||||
|
quotaHistory: z.array(
|
||||||
|
z.object({
|
||||||
|
addQuotaKb: z.union([z.string(), z.number()]),
|
||||||
|
addDate: z.string(),
|
||||||
|
expireDate: z.string(),
|
||||||
|
campaignCode: z.string().optional(),
|
||||||
|
})
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const freebitEsimMnpSchema = z.object({
|
||||||
|
reserveNumber: z.string().min(1, "Reserve number is required"),
|
||||||
|
reserveExpireDate: z.string().regex(/^\d{8}$/, "Reserve expire date must be in YYYYMMDD format"),
|
||||||
|
});
|
||||||
|
|
||||||
export const freebitEsimReissueRequestSchema = z.object({
|
export const freebitEsimReissueRequestSchema = z.object({
|
||||||
account: z.string().min(1, "Account is required"),
|
account: z.string().min(1, "Account is required"),
|
||||||
newEid: z.string().min(1, "New EID is required"),
|
newEid: z.string().min(1, "New EID is required"),
|
||||||
@ -98,9 +129,21 @@ export const freebitEsimReissueRequestSchema = z.object({
|
|||||||
oldProductNumber: z.string().optional(),
|
oldProductNumber: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
export const freebitEsimAddAccountRequestSchema = z.object({
|
||||||
|
authKey: z.string().min(1).optional(),
|
||||||
|
aladinOperated: z.enum(["10", "20"]).default("10"),
|
||||||
|
account: z.string().min(1, "Account is required"),
|
||||||
|
eid: z.string().min(1, "EID is required"),
|
||||||
|
addKind: z.enum(["N", "R"]).default("N"),
|
||||||
|
shipDate: z.string().regex(/^\d{8}$/, "Ship date must be in YYYYMMDD format").optional(),
|
||||||
|
planCode: z.string().optional(),
|
||||||
|
contractLine: z.enum(["4G", "5G"]).optional(),
|
||||||
|
mnp: freebitEsimMnpSchema.optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
// SIM Features
|
// SIM Features
|
||||||
// ============================================================================
|
// =========================================================================
|
||||||
|
|
||||||
export const freebitSimFeaturesRequestSchema = z.object({
|
export const freebitSimFeaturesRequestSchema = z.object({
|
||||||
account: z.string().min(1, "Account is required"),
|
account: z.string().min(1, "Account is required"),
|
||||||
@ -115,14 +158,9 @@ export const freebitGlobalIpRequestSchema = z.object({
|
|||||||
assign: z.boolean(), // true to assign, false to remove
|
assign: z.boolean(), // true to assign, false to remove
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// =========================================================================
|
||||||
// eSIM Activation
|
// eSIM Activation
|
||||||
// ============================================================================
|
// =========================================================================
|
||||||
|
|
||||||
export const freebitEsimMnpSchema = z.object({
|
|
||||||
reserveNumber: z.string().min(1, "Reserve number is required"),
|
|
||||||
reserveExpireDate: z.string().regex(/^\d{8}$/, "Reserve expire date must be in YYYYMMDD format"),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const freebitAuthRequestSchema = z.object({
|
export const freebitAuthRequestSchema = z.object({
|
||||||
oemId: z.string().min(1),
|
oemId: z.string().min(1),
|
||||||
|
|||||||
116
packages/domain/src/common.d.ts
vendored
116
packages/domain/src/common.d.ts
vendored
@ -1,116 +0,0 @@
|
|||||||
export type UserId = string & {
|
|
||||||
readonly __brand: "UserId";
|
|
||||||
};
|
|
||||||
export type OrderId = string & {
|
|
||||||
readonly __brand: "OrderId";
|
|
||||||
};
|
|
||||||
export type InvoiceId = string & {
|
|
||||||
readonly __brand: "InvoiceId";
|
|
||||||
};
|
|
||||||
export type SubscriptionId = string & {
|
|
||||||
readonly __brand: "SubscriptionId";
|
|
||||||
};
|
|
||||||
export type PaymentId = string & {
|
|
||||||
readonly __brand: "PaymentId";
|
|
||||||
};
|
|
||||||
export type CaseId = string & {
|
|
||||||
readonly __brand: "CaseId";
|
|
||||||
};
|
|
||||||
export type SessionId = string & {
|
|
||||||
readonly __brand: "SessionId";
|
|
||||||
};
|
|
||||||
export type WhmcsClientId = number & {
|
|
||||||
readonly __brand: "WhmcsClientId";
|
|
||||||
};
|
|
||||||
export type WhmcsInvoiceId = number & {
|
|
||||||
readonly __brand: "WhmcsInvoiceId";
|
|
||||||
};
|
|
||||||
export type WhmcsProductId = number & {
|
|
||||||
readonly __brand: "WhmcsProductId";
|
|
||||||
};
|
|
||||||
export type SalesforceContactId = string & {
|
|
||||||
readonly __brand: "SalesforceContactId";
|
|
||||||
};
|
|
||||||
export type SalesforceAccountId = string & {
|
|
||||||
readonly __brand: "SalesforceAccountId";
|
|
||||||
};
|
|
||||||
export type SalesforceCaseId = string & {
|
|
||||||
readonly __brand: "SalesforceCaseId";
|
|
||||||
};
|
|
||||||
export declare const createUserId: (id: string) => UserId;
|
|
||||||
export declare const createOrderId: (id: string) => OrderId;
|
|
||||||
export declare const createInvoiceId: (id: string) => InvoiceId;
|
|
||||||
export declare const createSubscriptionId: (id: string) => SubscriptionId;
|
|
||||||
export declare const createPaymentId: (id: string) => PaymentId;
|
|
||||||
export declare const createCaseId: (id: string) => CaseId;
|
|
||||||
export declare const createSessionId: (id: string) => SessionId;
|
|
||||||
export declare const createWhmcsClientId: (id: number) => WhmcsClientId;
|
|
||||||
export declare const createWhmcsInvoiceId: (id: number) => WhmcsInvoiceId;
|
|
||||||
export declare const createWhmcsProductId: (id: number) => WhmcsProductId;
|
|
||||||
export declare const createSalesforceContactId: (id: string) => SalesforceContactId;
|
|
||||||
export declare const createSalesforceAccountId: (id: string) => SalesforceAccountId;
|
|
||||||
export declare const createSalesforceCaseId: (id: string) => SalesforceCaseId;
|
|
||||||
export declare const isUserId: (id: string) => id is UserId;
|
|
||||||
export declare const isOrderId: (id: string) => id is OrderId;
|
|
||||||
export declare const isInvoiceId: (id: string) => id is InvoiceId;
|
|
||||||
export declare const isWhmcsClientId: (id: number) => id is WhmcsClientId;
|
|
||||||
export type IsoDateTimeString = string;
|
|
||||||
export interface BaseEntity {
|
|
||||||
id: string;
|
|
||||||
createdAt: string;
|
|
||||||
updatedAt: string;
|
|
||||||
}
|
|
||||||
export interface WhmcsEntity {
|
|
||||||
id: number;
|
|
||||||
}
|
|
||||||
export interface SalesforceEntity {
|
|
||||||
id: string;
|
|
||||||
createdDate: string;
|
|
||||||
lastModifiedDate: string;
|
|
||||||
}
|
|
||||||
export interface Paginated<T> {
|
|
||||||
items: T[];
|
|
||||||
nextCursor: string | null;
|
|
||||||
totalCount?: number;
|
|
||||||
}
|
|
||||||
export interface IdempotencyKey {
|
|
||||||
key: string;
|
|
||||||
userId: string;
|
|
||||||
createdAt: string;
|
|
||||||
}
|
|
||||||
export interface UserMapping {
|
|
||||||
userId: string;
|
|
||||||
whmcsClientId: number;
|
|
||||||
sfContactId?: string;
|
|
||||||
sfAccountId?: string;
|
|
||||||
createdAt?: Date;
|
|
||||||
updatedAt?: Date;
|
|
||||||
}
|
|
||||||
export interface UserIdMapping extends UserMapping {
|
|
||||||
createdAt?: Date;
|
|
||||||
updatedAt?: Date;
|
|
||||||
}
|
|
||||||
export interface CreateMappingRequest {
|
|
||||||
userId: string;
|
|
||||||
whmcsClientId: number;
|
|
||||||
sfAccountId?: string;
|
|
||||||
}
|
|
||||||
export interface UpdateMappingRequest {
|
|
||||||
whmcsClientId?: number;
|
|
||||||
sfAccountId?: string;
|
|
||||||
}
|
|
||||||
export interface MappingStats {
|
|
||||||
totalMappings: number;
|
|
||||||
whmcsMappings: number;
|
|
||||||
salesforceMappings: number;
|
|
||||||
completeMappings: number;
|
|
||||||
orphanedMappings: number;
|
|
||||||
}
|
|
||||||
export interface Address {
|
|
||||||
street: string | null;
|
|
||||||
streetLine2: string | null;
|
|
||||||
city: string | null;
|
|
||||||
state: string | null;
|
|
||||||
postalCode: string | null;
|
|
||||||
country: string | null;
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.isWhmcsClientId = exports.isInvoiceId = exports.isOrderId = exports.isUserId = exports.createSalesforceCaseId = exports.createSalesforceAccountId = exports.createSalesforceContactId = exports.createWhmcsProductId = exports.createWhmcsInvoiceId = exports.createWhmcsClientId = exports.createSessionId = exports.createCaseId = exports.createPaymentId = exports.createSubscriptionId = exports.createInvoiceId = exports.createOrderId = exports.createUserId = void 0;
|
|
||||||
const createUserId = (id) => id;
|
|
||||||
exports.createUserId = createUserId;
|
|
||||||
const createOrderId = (id) => id;
|
|
||||||
exports.createOrderId = createOrderId;
|
|
||||||
const createInvoiceId = (id) => id;
|
|
||||||
exports.createInvoiceId = createInvoiceId;
|
|
||||||
const createSubscriptionId = (id) => id;
|
|
||||||
exports.createSubscriptionId = createSubscriptionId;
|
|
||||||
const createPaymentId = (id) => id;
|
|
||||||
exports.createPaymentId = createPaymentId;
|
|
||||||
const createCaseId = (id) => id;
|
|
||||||
exports.createCaseId = createCaseId;
|
|
||||||
const createSessionId = (id) => id;
|
|
||||||
exports.createSessionId = createSessionId;
|
|
||||||
const createWhmcsClientId = (id) => id;
|
|
||||||
exports.createWhmcsClientId = createWhmcsClientId;
|
|
||||||
const createWhmcsInvoiceId = (id) => id;
|
|
||||||
exports.createWhmcsInvoiceId = createWhmcsInvoiceId;
|
|
||||||
const createWhmcsProductId = (id) => id;
|
|
||||||
exports.createWhmcsProductId = createWhmcsProductId;
|
|
||||||
const createSalesforceContactId = (id) => id;
|
|
||||||
exports.createSalesforceContactId = createSalesforceContactId;
|
|
||||||
const createSalesforceAccountId = (id) => id;
|
|
||||||
exports.createSalesforceAccountId = createSalesforceAccountId;
|
|
||||||
const createSalesforceCaseId = (id) => id;
|
|
||||||
exports.createSalesforceCaseId = createSalesforceCaseId;
|
|
||||||
const isUserId = (id) => typeof id === "string";
|
|
||||||
exports.isUserId = isUserId;
|
|
||||||
const isOrderId = (id) => typeof id === "string";
|
|
||||||
exports.isOrderId = isOrderId;
|
|
||||||
const isInvoiceId = (id) => typeof id === "string";
|
|
||||||
exports.isInvoiceId = isInvoiceId;
|
|
||||||
const isWhmcsClientId = (id) => typeof id === "number";
|
|
||||||
exports.isWhmcsClientId = isWhmcsClientId;
|
|
||||||
//# sourceMappingURL=common.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"common.js","sourceRoot":"","sources":["common.ts"],"names":[],"mappings":";;;AA0BO,MAAM,YAAY,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,EAAY,CAAC;AAApD,QAAA,YAAY,gBAAwC;AAC1D,MAAM,aAAa,GAAG,CAAC,EAAU,EAAW,EAAE,CAAC,EAAa,CAAC;AAAvD,QAAA,aAAa,iBAA0C;AAC7D,MAAM,eAAe,GAAG,CAAC,EAAU,EAAa,EAAE,CAAC,EAAe,CAAC;AAA7D,QAAA,eAAe,mBAA8C;AACnE,MAAM,oBAAoB,GAAG,CAAC,EAAU,EAAkB,EAAE,CAAC,EAAoB,CAAC;AAA5E,QAAA,oBAAoB,wBAAwD;AAClF,MAAM,eAAe,GAAG,CAAC,EAAU,EAAa,EAAE,CAAC,EAAe,CAAC;AAA7D,QAAA,eAAe,mBAA8C;AACnE,MAAM,YAAY,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,EAAY,CAAC;AAApD,QAAA,YAAY,gBAAwC;AAC1D,MAAM,eAAe,GAAG,CAAC,EAAU,EAAa,EAAE,CAAC,EAAe,CAAC;AAA7D,QAAA,eAAe,mBAA8C;AAEnE,MAAM,mBAAmB,GAAG,CAAC,EAAU,EAAiB,EAAE,CAAC,EAAmB,CAAC;AAAzE,QAAA,mBAAmB,uBAAsD;AAC/E,MAAM,oBAAoB,GAAG,CAAC,EAAU,EAAkB,EAAE,CAAC,EAAoB,CAAC;AAA5E,QAAA,oBAAoB,wBAAwD;AAClF,MAAM,oBAAoB,GAAG,CAAC,EAAU,EAAkB,EAAE,CAAC,EAAoB,CAAC;AAA5E,QAAA,oBAAoB,wBAAwD;AAElF,MAAM,yBAAyB,GAAG,CAAC,EAAU,EAAuB,EAAE,CAC3E,EAAyB,CAAC;AADf,QAAA,yBAAyB,6BACV;AACrB,MAAM,yBAAyB,GAAG,CAAC,EAAU,EAAuB,EAAE,CAC3E,EAAyB,CAAC;AADf,QAAA,yBAAyB,6BACV;AACrB,MAAM,sBAAsB,GAAG,CAAC,EAAU,EAAoB,EAAE,CAAC,EAAsB,CAAC;AAAlF,QAAA,sBAAsB,0BAA4D;AAGxF,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAgB,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC;AAAhE,QAAA,QAAQ,YAAwD;AACtE,MAAM,SAAS,GAAG,CAAC,EAAU,EAAiB,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC;AAAlE,QAAA,SAAS,aAAyD;AACxE,MAAM,WAAW,GAAG,CAAC,EAAU,EAAmB,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC;AAAtE,QAAA,WAAW,eAA2D;AAC5E,MAAM,eAAe,GAAG,CAAC,EAAU,EAAuB,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC;AAA9E,QAAA,eAAe,mBAA+D"}
|
|
||||||
@ -1,135 +0,0 @@
|
|||||||
// Common types used across the application
|
|
||||||
|
|
||||||
// =====================================================
|
|
||||||
// BRANDED TYPES FOR TYPE SAFETY
|
|
||||||
// =====================================================
|
|
||||||
|
|
||||||
// Branded types for critical identifiers
|
|
||||||
export type UserId = string & { readonly __brand: "UserId" };
|
|
||||||
export type OrderId = string & { readonly __brand: "OrderId" };
|
|
||||||
export type InvoiceId = string & { readonly __brand: "InvoiceId" };
|
|
||||||
export type SubscriptionId = string & { readonly __brand: "SubscriptionId" };
|
|
||||||
export type PaymentId = string & { readonly __brand: "PaymentId" };
|
|
||||||
export type CaseId = string & { readonly __brand: "CaseId" };
|
|
||||||
export type SessionId = string & { readonly __brand: "SessionId" };
|
|
||||||
|
|
||||||
// WHMCS-specific branded types
|
|
||||||
export type WhmcsClientId = number & { readonly __brand: "WhmcsClientId" };
|
|
||||||
export type WhmcsInvoiceId = number & { readonly __brand: "WhmcsInvoiceId" };
|
|
||||||
export type WhmcsProductId = number & { readonly __brand: "WhmcsProductId" };
|
|
||||||
|
|
||||||
// Salesforce-specific branded types
|
|
||||||
export type SalesforceContactId = string & { readonly __brand: "SalesforceContactId" };
|
|
||||||
export type SalesforceAccountId = string & { readonly __brand: "SalesforceAccountId" };
|
|
||||||
export type SalesforceCaseId = string & { readonly __brand: "SalesforceCaseId" };
|
|
||||||
|
|
||||||
// Helper functions for creating branded types
|
|
||||||
export const createUserId = (id: string): UserId => id as UserId;
|
|
||||||
export const createOrderId = (id: string): OrderId => id as OrderId;
|
|
||||||
export const createInvoiceId = (id: string): InvoiceId => id as InvoiceId;
|
|
||||||
export const createSubscriptionId = (id: string): SubscriptionId => id as SubscriptionId;
|
|
||||||
export const createPaymentId = (id: string): PaymentId => id as PaymentId;
|
|
||||||
export const createCaseId = (id: string): CaseId => id as CaseId;
|
|
||||||
export const createSessionId = (id: string): SessionId => id as SessionId;
|
|
||||||
|
|
||||||
export const createWhmcsClientId = (id: number): WhmcsClientId => id as WhmcsClientId;
|
|
||||||
export const createWhmcsInvoiceId = (id: number): WhmcsInvoiceId => id as WhmcsInvoiceId;
|
|
||||||
export const createWhmcsProductId = (id: number): WhmcsProductId => id as WhmcsProductId;
|
|
||||||
|
|
||||||
export const createSalesforceContactId = (id: string): SalesforceContactId =>
|
|
||||||
id as SalesforceContactId;
|
|
||||||
export const createSalesforceAccountId = (id: string): SalesforceAccountId =>
|
|
||||||
id as SalesforceAccountId;
|
|
||||||
export const createSalesforceCaseId = (id: string): SalesforceCaseId => id as SalesforceCaseId;
|
|
||||||
|
|
||||||
// Type guards for branded types
|
|
||||||
export const isUserId = (id: string): id is UserId => typeof id === "string";
|
|
||||||
export const isOrderId = (id: string): id is OrderId => typeof id === "string";
|
|
||||||
export const isInvoiceId = (id: string): id is InvoiceId => typeof id === "string";
|
|
||||||
export const isWhmcsClientId = (id: number): id is WhmcsClientId => typeof id === "number";
|
|
||||||
|
|
||||||
// Shared ISO8601 timestamp string type used for serialized dates
|
|
||||||
export type IsoDateTimeString = string;
|
|
||||||
|
|
||||||
// =====================================================
|
|
||||||
// BASE ENTITY INTERFACES
|
|
||||||
// =====================================================
|
|
||||||
|
|
||||||
// Base entity interfaces for different systems
|
|
||||||
|
|
||||||
// Portal entities (User, etc.)
|
|
||||||
export interface BaseEntity {
|
|
||||||
id: string;
|
|
||||||
createdAt: string;
|
|
||||||
updatedAt: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// WHMCS entities (Invoice, Subscription, etc.)
|
|
||||||
export interface WhmcsEntity {
|
|
||||||
id: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Salesforce entities (SupportCase, etc.)
|
|
||||||
export interface SalesforceEntity {
|
|
||||||
id: string;
|
|
||||||
createdDate: string;
|
|
||||||
lastModifiedDate: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Paginated<T> {
|
|
||||||
items: T[];
|
|
||||||
nextCursor: string | null;
|
|
||||||
totalCount?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
// API types moved to contracts/api.ts
|
|
||||||
|
|
||||||
export interface IdempotencyKey {
|
|
||||||
key: string;
|
|
||||||
userId: string;
|
|
||||||
createdAt: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserMapping {
|
|
||||||
userId: string;
|
|
||||||
whmcsClientId: number;
|
|
||||||
sfContactId?: string;
|
|
||||||
sfAccountId?: string;
|
|
||||||
createdAt?: Date;
|
|
||||||
updatedAt?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extended mapping interfaces for V2 implementation
|
|
||||||
export interface UserIdMapping extends UserMapping {
|
|
||||||
createdAt?: Date;
|
|
||||||
updatedAt?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateMappingRequest {
|
|
||||||
userId: string;
|
|
||||||
whmcsClientId: number;
|
|
||||||
sfAccountId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpdateMappingRequest {
|
|
||||||
whmcsClientId?: number;
|
|
||||||
sfAccountId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MappingStats {
|
|
||||||
totalMappings: number;
|
|
||||||
whmcsMappings: number;
|
|
||||||
salesforceMappings: number;
|
|
||||||
completeMappings: number;
|
|
||||||
orphanedMappings: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shared address type used across BFF and Portal
|
|
||||||
export interface Address {
|
|
||||||
street: string | null;
|
|
||||||
streetLine2: string | null;
|
|
||||||
city: string | null;
|
|
||||||
state: string | null;
|
|
||||||
postalCode: string | null;
|
|
||||||
country: string | null;
|
|
||||||
}
|
|
||||||
75
packages/domain/src/contracts/api.d.ts
vendored
75
packages/domain/src/contracts/api.d.ts
vendored
@ -1,75 +0,0 @@
|
|||||||
export type ApiResponse<T = unknown> = ApiSuccess<T> | ApiFailure;
|
|
||||||
export interface ApiSuccess<T = unknown> {
|
|
||||||
success: true;
|
|
||||||
data: T;
|
|
||||||
meta?: ApiMeta;
|
|
||||||
}
|
|
||||||
export interface ApiFailure {
|
|
||||||
success: false;
|
|
||||||
error: ApiError;
|
|
||||||
meta?: ApiMeta;
|
|
||||||
}
|
|
||||||
export interface ApiError {
|
|
||||||
code: string;
|
|
||||||
message: string;
|
|
||||||
details?: Record<string, unknown>;
|
|
||||||
statusCode?: number;
|
|
||||||
timestamp?: string;
|
|
||||||
path?: string;
|
|
||||||
}
|
|
||||||
export interface ApiMeta {
|
|
||||||
requestId?: string;
|
|
||||||
timestamp?: string;
|
|
||||||
version?: string;
|
|
||||||
}
|
|
||||||
export interface PaginatedResponse<T> {
|
|
||||||
data: T[];
|
|
||||||
pagination: {
|
|
||||||
page: number;
|
|
||||||
limit: number;
|
|
||||||
total: number;
|
|
||||||
totalPages: number;
|
|
||||||
hasNext: boolean;
|
|
||||||
hasPrev: boolean;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export interface QueryParams extends Record<string, unknown> {
|
|
||||||
page?: number;
|
|
||||||
limit?: number;
|
|
||||||
search?: string;
|
|
||||||
filter?: Record<string, unknown>;
|
|
||||||
sort?: string;
|
|
||||||
}
|
|
||||||
export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
||||||
export interface ApiRequestConfig {
|
|
||||||
method?: HttpMethod;
|
|
||||||
headers?: Record<string, string>;
|
|
||||||
params?: QueryParams;
|
|
||||||
data?: unknown;
|
|
||||||
timeout?: number;
|
|
||||||
retries?: number;
|
|
||||||
cache?: boolean;
|
|
||||||
}
|
|
||||||
export interface ApiClient {
|
|
||||||
get<T>(url: string, config?: ApiRequestConfig): Promise<ApiResponse<T>>;
|
|
||||||
post<T>(url: string, data?: unknown, config?: ApiRequestConfig): Promise<ApiResponse<T>>;
|
|
||||||
put<T>(url: string, data?: unknown, config?: ApiRequestConfig): Promise<ApiResponse<T>>;
|
|
||||||
patch<T>(url: string, data?: unknown, config?: ApiRequestConfig): Promise<ApiResponse<T>>;
|
|
||||||
delete<T>(url: string, config?: ApiRequestConfig): Promise<ApiResponse<T>>;
|
|
||||||
}
|
|
||||||
export interface ApiClientError {
|
|
||||||
code?: string;
|
|
||||||
message: string;
|
|
||||||
details?: Record<string, unknown>;
|
|
||||||
statusCode?: number;
|
|
||||||
timestamp?: string;
|
|
||||||
}
|
|
||||||
export type RequestInterceptor = (config: ApiRequestConfig) => ApiRequestConfig | Promise<ApiRequestConfig>;
|
|
||||||
export type ResponseInterceptor = <T>(response: ApiResponse<T>) => ApiResponse<T> | Promise<ApiResponse<T>>;
|
|
||||||
export interface CrudService<T, CreateT = Partial<T>, UpdateT = Partial<T>> {
|
|
||||||
getAll(params?: QueryParams): Promise<PaginatedResponse<T>>;
|
|
||||||
getById(id: string): Promise<T>;
|
|
||||||
create(data: CreateT): Promise<T>;
|
|
||||||
update(id: string, data: UpdateT): Promise<T>;
|
|
||||||
delete(id: string): Promise<void>;
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
//# sourceMappingURL=api.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"api.js","sourceRoot":"","sources":["api.ts"],"names":[],"mappings":""}
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
// API response envelope types
|
|
||||||
export type ApiResponse<T = unknown> = ApiSuccess<T> | ApiFailure;
|
|
||||||
|
|
||||||
export interface ApiSuccess<T = unknown> {
|
|
||||||
success: true;
|
|
||||||
data: T;
|
|
||||||
meta?: ApiMeta;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ApiFailure {
|
|
||||||
success: false;
|
|
||||||
error: ApiError;
|
|
||||||
meta?: ApiMeta;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ApiError {
|
|
||||||
code: string;
|
|
||||||
message: string;
|
|
||||||
details?: Record<string, unknown>;
|
|
||||||
statusCode?: number;
|
|
||||||
timestamp?: string;
|
|
||||||
path?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ApiMeta {
|
|
||||||
requestId?: string;
|
|
||||||
timestamp?: string;
|
|
||||||
version?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generic pagination interface (business contract)
|
|
||||||
export interface PaginatedResponse<T> {
|
|
||||||
data: T[];
|
|
||||||
pagination: {
|
|
||||||
page: number;
|
|
||||||
limit: number;
|
|
||||||
total: number;
|
|
||||||
totalPages: number;
|
|
||||||
hasNext: boolean;
|
|
||||||
hasPrev: boolean;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query parameters for API requests (business contract)
|
|
||||||
export interface QueryParams extends Record<string, unknown> {
|
|
||||||
page?: number;
|
|
||||||
limit?: number;
|
|
||||||
search?: string;
|
|
||||||
filter?: Record<string, unknown>;
|
|
||||||
sort?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP methods (technical contract)
|
|
||||||
export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
||||||
|
|
||||||
// API request configuration (technical contract)
|
|
||||||
export interface ApiRequestConfig {
|
|
||||||
method?: HttpMethod;
|
|
||||||
headers?: Record<string, string>;
|
|
||||||
params?: QueryParams;
|
|
||||||
data?: unknown;
|
|
||||||
timeout?: number;
|
|
||||||
retries?: number;
|
|
||||||
cache?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
// API client interface (technical contract)
|
|
||||||
export interface ApiClient {
|
|
||||||
get<T>(url: string, config?: ApiRequestConfig): Promise<ApiResponse<T>>;
|
|
||||||
post<T>(url: string, data?: unknown, config?: ApiRequestConfig): Promise<ApiResponse<T>>;
|
|
||||||
put<T>(url: string, data?: unknown, config?: ApiRequestConfig): Promise<ApiResponse<T>>;
|
|
||||||
patch<T>(url: string, data?: unknown, config?: ApiRequestConfig): Promise<ApiResponse<T>>;
|
|
||||||
delete<T>(url: string, config?: ApiRequestConfig): Promise<ApiResponse<T>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// API client error interface (technical contract)
|
|
||||||
export interface ApiClientError {
|
|
||||||
code?: string;
|
|
||||||
message: string;
|
|
||||||
details?: Record<string, unknown>;
|
|
||||||
statusCode?: number;
|
|
||||||
timestamp?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interceptor types (technical contract)
|
|
||||||
export type RequestInterceptor = (
|
|
||||||
config: ApiRequestConfig
|
|
||||||
) => ApiRequestConfig | Promise<ApiRequestConfig>;
|
|
||||||
|
|
||||||
export type ResponseInterceptor = <T>(
|
|
||||||
response: ApiResponse<T>
|
|
||||||
) => ApiResponse<T> | Promise<ApiResponse<T>>;
|
|
||||||
|
|
||||||
// Generic CRUD service interface (business contract)
|
|
||||||
export interface CrudService<T, CreateT = Partial<T>, UpdateT = Partial<T>> {
|
|
||||||
getAll(params?: QueryParams): Promise<PaginatedResponse<T>>;
|
|
||||||
getById(id: string): Promise<T>;
|
|
||||||
create(data: CreateT): Promise<T>;
|
|
||||||
update(id: string, data: UpdateT): Promise<T>;
|
|
||||||
delete(id: string): Promise<void>;
|
|
||||||
}
|
|
||||||
60
packages/domain/src/contracts/catalog.d.ts
vendored
60
packages/domain/src/contracts/catalog.d.ts
vendored
@ -1,60 +0,0 @@
|
|||||||
export interface CatalogProductBase {
|
|
||||||
id: string;
|
|
||||||
sku: string;
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
displayOrder?: number;
|
|
||||||
billingCycle?: string;
|
|
||||||
monthlyPrice?: number;
|
|
||||||
oneTimePrice?: number;
|
|
||||||
unitPrice?: number;
|
|
||||||
}
|
|
||||||
export interface InternetCatalogProduct extends CatalogProductBase {
|
|
||||||
internetPlanTier?: string;
|
|
||||||
internetOfferingType?: string;
|
|
||||||
features?: string[];
|
|
||||||
}
|
|
||||||
export interface InternetPlanTemplate {
|
|
||||||
tierDescription: string;
|
|
||||||
description?: string;
|
|
||||||
features?: string[];
|
|
||||||
}
|
|
||||||
export interface InternetPlanCatalogItem extends InternetCatalogProduct {
|
|
||||||
catalogMetadata?: {
|
|
||||||
tierDescription?: string;
|
|
||||||
features?: string[];
|
|
||||||
isRecommended?: boolean;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export interface InternetInstallationCatalogItem extends InternetCatalogProduct {
|
|
||||||
catalogMetadata?: {
|
|
||||||
installationTerm: "One-time" | "12-Month" | "24-Month";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export interface InternetAddonCatalogItem extends InternetCatalogProduct {
|
|
||||||
isBundledAddon?: boolean;
|
|
||||||
bundledAddonId?: string;
|
|
||||||
}
|
|
||||||
export interface SimCatalogProduct extends CatalogProductBase {
|
|
||||||
simDataSize?: string;
|
|
||||||
simPlanType?: string;
|
|
||||||
simHasFamilyDiscount?: boolean;
|
|
||||||
isBundledAddon?: boolean;
|
|
||||||
bundledAddonId?: string;
|
|
||||||
}
|
|
||||||
export interface SimActivationFeeCatalogItem extends SimCatalogProduct {
|
|
||||||
catalogMetadata?: {
|
|
||||||
isDefault: boolean;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export interface VpnCatalogProduct extends CatalogProductBase {
|
|
||||||
vpnRegion?: string;
|
|
||||||
}
|
|
||||||
export interface CatalogPricebookEntry {
|
|
||||||
id?: string;
|
|
||||||
name?: string;
|
|
||||||
unitPrice?: number;
|
|
||||||
pricebook2Id?: string;
|
|
||||||
product2Id?: string;
|
|
||||||
isActive?: boolean;
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
//# sourceMappingURL=catalog.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["catalog.ts"],"names":[],"mappings":""}
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
// Shared catalog contracts consumed by both BFF and Portal
|
|
||||||
|
|
||||||
export interface CatalogProductBase {
|
|
||||||
id: string;
|
|
||||||
sku: string;
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
displayOrder?: number;
|
|
||||||
billingCycle?: string;
|
|
||||||
monthlyPrice?: number;
|
|
||||||
oneTimePrice?: number;
|
|
||||||
unitPrice?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface InternetCatalogProduct extends CatalogProductBase {
|
|
||||||
internetPlanTier?: string;
|
|
||||||
internetOfferingType?: string;
|
|
||||||
features?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface InternetPlanTemplate {
|
|
||||||
tierDescription: string;
|
|
||||||
description?: string;
|
|
||||||
features?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface InternetPlanCatalogItem extends InternetCatalogProduct {
|
|
||||||
catalogMetadata?: {
|
|
||||||
tierDescription?: string;
|
|
||||||
features?: string[];
|
|
||||||
isRecommended?: boolean;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface InternetInstallationCatalogItem extends InternetCatalogProduct {
|
|
||||||
catalogMetadata?: {
|
|
||||||
installationTerm: "One-time" | "12-Month" | "24-Month";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface InternetAddonCatalogItem extends InternetCatalogProduct {
|
|
||||||
isBundledAddon?: boolean;
|
|
||||||
bundledAddonId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SimCatalogProduct extends CatalogProductBase {
|
|
||||||
simDataSize?: string;
|
|
||||||
simPlanType?: string;
|
|
||||||
simHasFamilyDiscount?: boolean;
|
|
||||||
isBundledAddon?: boolean;
|
|
||||||
bundledAddonId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SimActivationFeeCatalogItem extends SimCatalogProduct {
|
|
||||||
catalogMetadata?: {
|
|
||||||
isDefault: boolean;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export interface VpnCatalogProduct extends CatalogProductBase {
|
|
||||||
vpnRegion?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CatalogPricebookEntry {
|
|
||||||
id?: string;
|
|
||||||
name?: string;
|
|
||||||
unitPrice?: number;
|
|
||||||
pricebook2Id?: string;
|
|
||||||
product2Id?: string;
|
|
||||||
isActive?: boolean;
|
|
||||||
}
|
|
||||||
3
packages/domain/src/contracts/index.d.ts
vendored
3
packages/domain/src/contracts/index.d.ts
vendored
@ -1,3 +0,0 @@
|
|||||||
export * from "./api";
|
|
||||||
export * from "./catalog";
|
|
||||||
export * from "./salesforce";
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
||||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
||||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
||||||
}
|
|
||||||
Object.defineProperty(o, k2, desc);
|
|
||||||
}) : (function(o, m, k, k2) {
|
|
||||||
if (k2 === undefined) k2 = k;
|
|
||||||
o[k2] = m[k];
|
|
||||||
}));
|
|
||||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
||||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
__exportStar(require("./api"), exports);
|
|
||||||
__exportStar(require("./catalog"), exports);
|
|
||||||
__exportStar(require("./salesforce"), exports);
|
|
||||||
//# sourceMappingURL=index.js.map
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AACA,wCAAsB;AACtB,4CAA0B;AAC1B,+CAA6B"}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user