219 lines
5.9 KiB
TypeScript
219 lines
5.9 KiB
TypeScript
import { IV_Product as CwIVProduct } from "../../generated/prisma/client";
|
|
import { Translation, skipRow } from "./types";
|
|
import { TranslationContext } from "./context";
|
|
|
|
type ApiProductDataRecord = {
|
|
id: number;
|
|
qty: number;
|
|
internalNote?: string | null;
|
|
shortDescription?: string | null;
|
|
description?: string | null;
|
|
sequenceNumber?: number | null;
|
|
procurementNotes?: string | null;
|
|
productNarrative?: string | null;
|
|
unitPrice: number;
|
|
unitCost: number;
|
|
listPrice: number;
|
|
discount: number;
|
|
recurringRevenue: number;
|
|
recurringCost: number;
|
|
qtyPicked: number;
|
|
qtyShipped: number;
|
|
cancelReason?: string | null;
|
|
cancelQty?: number | null;
|
|
billableFlag: boolean;
|
|
taxableFlag: boolean;
|
|
invoiceFlag: boolean;
|
|
recurringFlag: boolean;
|
|
poApprovedFlag: boolean;
|
|
calcPriceFlag: boolean;
|
|
calcCostFlag: boolean;
|
|
cancelFlag: boolean;
|
|
catalogItemId: number;
|
|
corporateLocationId: number;
|
|
serviceTicketId?: number | null;
|
|
opportunityId?: number | null;
|
|
updatedById?: string | null;
|
|
createdById?: string | null;
|
|
closedById?: string | null;
|
|
cancelById: string;
|
|
closedAt?: Date | null;
|
|
cancelledAt?: Date | null;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
};
|
|
|
|
const toInt = (value: unknown, fallback = 0): number => {
|
|
if (value == null) return fallback;
|
|
const numeric = Number(value);
|
|
if (!Number.isFinite(numeric)) return fallback;
|
|
return Math.trunc(numeric);
|
|
};
|
|
|
|
const toNumber = (value: unknown, fallback = 0): number => {
|
|
if (value == null) return fallback;
|
|
const numeric = Number(value);
|
|
return Number.isFinite(numeric) ? numeric : fallback;
|
|
};
|
|
|
|
export const productDataTranslation: Translation<
|
|
CwIVProduct,
|
|
ApiProductDataRecord,
|
|
TranslationContext
|
|
> = {
|
|
values: [
|
|
{ from: "ivProductRecId", to: "id" },
|
|
{
|
|
from: "quantity",
|
|
to: "qty",
|
|
process: (value) => toNumber(value, 1),
|
|
},
|
|
{ from: "internalNote", to: "internalNote" },
|
|
{ from: "shortDescription", to: "shortDescription" },
|
|
{ from: "description", to: "description" },
|
|
{
|
|
from: "ivProductRecId",
|
|
to: "procurementNotes",
|
|
process: (value, context) => {
|
|
const custom = context.productCustomByIvProductId.get(value);
|
|
return custom?.procurementNotes ?? null;
|
|
},
|
|
},
|
|
{
|
|
from: "ivProductRecId",
|
|
to: "productNarrative",
|
|
process: (value, context) => {
|
|
const custom = context.productCustomByIvProductId.get(value);
|
|
return custom?.productNarrative ?? null;
|
|
},
|
|
},
|
|
{
|
|
from: "sequenceNumber",
|
|
to: "sequenceNumber",
|
|
process: (value) => (value == null ? null : toInt(value, 0)),
|
|
},
|
|
{
|
|
from: "unitPrice",
|
|
to: "unitPrice",
|
|
process: (value) => toNumber(value, 0),
|
|
},
|
|
{
|
|
from: "unitCost",
|
|
to: "unitCost",
|
|
process: (value) => toNumber(value, 0),
|
|
},
|
|
{
|
|
from: "listPrice",
|
|
to: "listPrice",
|
|
process: (value) => toNumber(value, 0),
|
|
},
|
|
{
|
|
from: "discountAmount",
|
|
to: "discount",
|
|
process: (value) => toNumber(value, 0),
|
|
},
|
|
{
|
|
from: "recurringRevenue",
|
|
to: "recurringRevenue",
|
|
process: (value) => toNumber(value, 0),
|
|
},
|
|
{
|
|
from: "recurringCost",
|
|
to: "recurringCost",
|
|
process: (value) => toNumber(value, 0),
|
|
},
|
|
{
|
|
from: "qtyPicked",
|
|
to: "qtyPicked",
|
|
process: (value) => toInt(value, 0),
|
|
},
|
|
{
|
|
from: "qtyShipped",
|
|
to: "qtyShipped",
|
|
process: (value) => toInt(value, 0),
|
|
},
|
|
{ from: "cancelReason", to: "cancelReason" },
|
|
{
|
|
from: "quantityCancelled",
|
|
to: "cancelQty",
|
|
process: (value) => (value == null ? null : toNumber(value, 0)),
|
|
},
|
|
{ from: "billableFlag", to: "billableFlag" },
|
|
{ from: "taxableFlag", to: "taxableFlag" },
|
|
{ from: "invoiceFlag", to: "invoiceFlag" },
|
|
{ from: "recurringFlag", to: "recurringFlag" },
|
|
{ from: "poApprovedFlag", to: "poApprovedFlag" },
|
|
{ from: "calcPriceFlag", to: "calcPriceFlag" },
|
|
{ from: "calcCostFlag", to: "calcCostFlag" },
|
|
{ from: "cancelFlag", to: "cancelFlag" },
|
|
{
|
|
from: "catalogRecId",
|
|
to: "catalogItemId",
|
|
process: (value, context) => {
|
|
if (!context.catalogItemIds.has(value)) {
|
|
skipRow(
|
|
`ProductData catalog item missing for catalogRecId ${value}`
|
|
);
|
|
}
|
|
return value;
|
|
},
|
|
},
|
|
{
|
|
from: "ownerLevelRecId",
|
|
to: "corporateLocationId",
|
|
process: (value, context) => {
|
|
if (!context.corporateLocationIds.has(value)) {
|
|
skipRow(
|
|
`ProductData corporate location missing for ownerLevelRecId ${value}`
|
|
);
|
|
}
|
|
return value;
|
|
},
|
|
},
|
|
{
|
|
from: "srServiceRecId",
|
|
to: "serviceTicketId",
|
|
process: (value, context) => {
|
|
if (value == null) return null;
|
|
return context.serviceTicketIds.has(value) ? value : null;
|
|
},
|
|
},
|
|
{
|
|
from: "opportunityRecId",
|
|
to: "opportunityId",
|
|
process: (value, context) => {
|
|
if (value == null) return null;
|
|
return context.opportunityIds.has(value) ? value : null;
|
|
},
|
|
},
|
|
{ from: "updatedBy", to: "updatedById" },
|
|
{ from: "enteredBy", to: "createdById" },
|
|
{ from: "closedBy", to: "closedById" },
|
|
{
|
|
from: "cancelBy",
|
|
to: "cancelById",
|
|
process: (value, context) => {
|
|
if (value == null) return "system";
|
|
return context.usersByMemberRecId.get(value) ?? `cw-member:${value}`;
|
|
},
|
|
},
|
|
{ from: "dateClosedUtc", to: "closedAt" },
|
|
{ from: "cancelDateUtc", to: "cancelledAt" },
|
|
{
|
|
from: "dateEntered",
|
|
to: "createdAt",
|
|
process: (value) => value ?? new Date(0),
|
|
},
|
|
{
|
|
from: "dateEnteredUtc",
|
|
to: "createdAt",
|
|
process: (value) => value ?? new Date(0),
|
|
},
|
|
{
|
|
from: "lastUpdatedUTC",
|
|
to: "updatedAt",
|
|
process: (value) => value ?? new Date(0),
|
|
},
|
|
],
|
|
};
|