@bisondesk/core-sdk 1.0.368 → 1.0.370

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offers.js","sourceRoot":"/","sources":["types/offers.ts"],"names":[],"mappings":"AASA,MAAM,CAAN,IAAY,YAcX;AAdD,WAAY,YAAY;IACtB,yCAAyB,CAAA;IACzB,2DAA2C,CAAA;IAC3C,6BAAa,CAAA;IACb,iCAAiB,CAAA;IACjB,+CAA+B,CAAA;IAC/B,6CAA6B,CAAA;IAC7B,6CAA6B,CAAA;IAC7B,6CAA6B,CAAA;IAC7B,uCAAuB,CAAA;IACvB,qDAAqC,CAAA;IACrC,yDAAyC,CAAA;IACzC,mEAAmD,CAAA;IACnD,6DAA6C,CAAA;AAC/C,CAAC,EAdW,YAAY,KAAZ,YAAY,QAcvB;AAED,MAAM,CAAN,IAAY,eAGX;AAHD,WAAY,eAAe;IACzB,0CAAuB,CAAA;IACvB,4CAAyB,CAAA;AAC3B,CAAC,EAHW,eAAe,KAAf,eAAe,QAG1B;AAED,MAAM,CAAN,IAAY,WAIX;AAJD,WAAY,WAAW;IACrB,0CAA2B,CAAA;IAC3B,sCAAuB,CAAA;IACvB,0CAA2B,CAAA;AAC7B,CAAC,EAJW,WAAW,KAAX,WAAW,QAItB;AAED,MAAM,CAAN,IAAY,qBAMX;AAND,WAAY,qBAAqB;IAC/B,gDAAuB,CAAA;IACvB,+CAAsB,CAAA;IACtB,yDAAgC,CAAA;IAChC,kDAAyB,CAAA;IACzB,gDAAuB,CAAA;AACzB,CAAC,EANW,qBAAqB,KAArB,qBAAqB,QAMhC;AAED,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,qCAAqB,CAAA;IACrB,qCAAqB,CAAA;AACvB,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB;AAED,MAAM,CAAN,IAAY,iBAEX;AAFD,WAAY,iBAAiB;IAC3B,gDAA2B,CAAA;AAC7B,CAAC,EAFW,iBAAiB,KAAjB,iBAAiB,QAE5B;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAkB;IAC7C,WAAW,CAAC,WAAW;IACvB,WAAW,CAAC,SAAS;IACrB,WAAW,CAAC,WAAW;CACxB,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,YAAY,CAAC;AAE7C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAG,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;AAE1E,MAAM,CAAC,MAAM,qBAAqB,GAAa,CAAC,gBAAgB,CAAC,CAAC","sourcesContent":["import { DistributiveOmit, Document, NextList } from '@bisondesk/commons-sdk/types';\nimport { BusinessEntityIds, WarningHints } from '../constants.js';\nimport { Contact, Organization } from './crm.js';\nimport { Insights, InsightsComparableSpecs } from './insights.js';\nimport { ContactMetdata } from './opportunities.js';\nimport { BaseSearchRequest } from './search.js';\nimport { DataRecord, ReferenceData } from './utils.js';\nimport { VehicleExternalInfo } from './vehicles.js';\n\nexport enum OfferActions {\n CREATE_BID = 'create_bid',\n SET_FINAL_VALUATION = 'set_final_valuation',\n LOSE = 'lose',\n REOPEN = 'reopen',\n SET_DOCUMENTS = 'set_documents',\n SET_METADATA = 'set_metadata',\n SEE_SUPPLIER = 'see_supplier',\n SEE_INSIGHTS = 'see_insights',\n VIEW_BIDS = 'view_bids',\n SEE_ASKING_PRICE = 'see_asking_price',\n ACCEPT_NEGOTIATION = 'accept_negotiation',\n UNDO_ACCEPT_NEGOTIATION = 'undo_accept_negotiation',\n SET_SUPPLIER_VEHICLE = 'set_supplier_vehicle',\n}\n\nexport enum OfferBidActions {\n EDIT_BID = 'create_bid',\n DELETE_BID = 'delete_bid',\n}\n\nexport enum OfferStatus {\n PROSPECTION = 'prospection', // initial status\n VALUATION = 'valuation', // has at least one internal or external bid with bid amount > 0\n NEGOTIATION = 'negotiation', // there is a final valuation, purchaser is talking to the supplier\n}\n\nexport enum OfferLostReasonValues {\n Expensive = 'expensive',\n NoMarket = 'no_market',\n BadExperience = 'bad_experience',\n NoAnswer = 'supplier_mia',\n Automatic = 'automatic',\n}\n\nexport enum OfferBidType {\n INTERNAL = 'internal',\n EXTERNAL = 'external',\n}\n\nexport enum OfferWarningsCode {\n NO_SUPPLIER = 'no_supplier',\n}\n\nexport const OfferStatusOrder: OfferStatus[] = [\n OfferStatus.PROSPECTION,\n OfferStatus.VALUATION,\n OfferStatus.NEGOTIATION,\n];\n\nexport const OfferWonColumnId = 'closed_won';\n\nexport const OfferKanbanColumns = [...OfferStatusOrder, OfferWonColumnId];\n\nexport const OfferKanbanEndColumns: string[] = [OfferWonColumnId];\n\ntype BaseOffer = {\n branchId: string;\n availableWeek?: string; // ISOWEEK, e.g. 2016-W02\n askingPrice?: string;\n currency?: string;\n quantity: number;\n specs: VehicleExternalInfo;\n documents: Document[];\n source?: string; // e.g., website, email, visit\n contactId: string;\n organizationId?: string;\n\n supplierNotes?: string; // Optional notes from the supplier\n};\n\nexport type NewOffer = BaseOffer & {\n id?: undefined;\n createdAt?: undefined;\n createdBy?: undefined;\n modifiedAt?: undefined;\n modifiedBy?: undefined;\n};\n\nexport type Offer = BaseOffer & {\n id: string;\n accountManager?: string; // optional since some offers might come directly from the internet\n createdAt: string;\n createdBy: string;\n modifiedAt: string;\n modifiedBy: string;\n firstBidAt?: string;\n\n lostReason?: OfferLostReasonValues;\n status: OfferStatus;\n quantity: number;\n\n appPrice?: string;\n appAvailability: boolean;\n\n wonAt?: string;\n wonBy?: string;\n lostAt?: string;\n lostBy?: string;\n\n valuation?: { amount: string; valuationAt: string; valuationBy: string };\n\n agreedAt?: string;\n agreedBy?: string;\n};\n\nexport type OfferUpdate = {\n accountManager?: string | null;\n branchId?: string | null;\n supplierNotes?: string | null;\n contactId?: string | null;\n organizationId?: string | null;\n lost?: boolean;\n lostReason?: OfferLostReasonValues;\n source?: string;\n askingPrice?: string;\n currency?: string;\n quantity?: number;\n specs?: VehicleExternalInfo;\n addNewBid?: boolean;\n documents?: Document[];\n appAvailability?: boolean;\n\n finalValuation?: string;\n agreed?: boolean;\n};\n\ntype OfferWarningActionLink = {\n businessEntityId: BusinessEntityIds;\n recordId: string;\n};\n\ntype OfferWarningActionData = { [key: string]: string | number };\n\nexport type OfferWarning = {\n code: OfferWarningsCode;\n level: WarningHints;\n link?: OfferWarningActionLink;\n data?: OfferWarningActionData;\n showAction?: boolean;\n};\n\nexport type OfferMetadata = {\n insights: {\n online: Pick<Insights['online'], 'count' | 'percentilesDays' | 'percentilesPrices'>;\n sold: Pick<Insights['sold'], 'count' | 'percentilesPrices' | 'percentilesDays'>;\n };\n stock: {\n available: number;\n leads: number;\n };\n comparable: InsightsComparableSpecs;\n warnings: OfferWarning[];\n};\n\nexport type OfferBff = {\n offer: DataRecord<Offer, OfferMetadata>;\n bids: DataRecord<OfferBid>[];\n customer?: {\n contact: DataRecord<Contact>;\n org?: DataRecord<Organization>;\n };\n};\n\n/************\n *\n * Bids\n */\n\ntype BaseOfferBid = {\n id: string;\n createdAt: string;\n createdBy: string;\n modifiedAt: string;\n modifiedBy: string;\n offerId: string;\n amount: string;\n currency: string;\n description?: string;\n deleted: boolean;\n};\n\nexport type InternalOfferBid = BaseOfferBid & {\n userId: string;\n final?: boolean; // Optional flag to indicate if this is the final valuation\n type: OfferBidType.INTERNAL;\n};\n\nexport type ExternalOfferBid = BaseOfferBid & {\n contactId: string;\n organizationId: string;\n notes?: string;\n type: OfferBidType.EXTERNAL;\n};\n\nexport type OfferBid = InternalOfferBid | ExternalOfferBid;\n\nexport type NewOfferBid = DistributiveOmit<\n OfferBid,\n 'id' | 'createdAt' | 'createdBy' | 'modifiedAt' | 'modifiedBy' | 'deleted'\n>;\n\nexport type InternalOfferBidUpdate = {\n amount?: string | null;\n currency?: string | null;\n description?: string | null;\n};\n\n/************\n *\n * Search\n */\n\nexport type SearchOffer = {\n contact?: Contact;\n offer: Offer;\n org?: Organization;\n custom: {\n lost: boolean;\n status: OfferStatus | 'won';\n totalBids: number;\n };\n};\n\nexport type AppOffer = {\n id: string;\n branchId: string;\n createdAt: string;\n unavailableAt?: string;\n\n availableWeek?: string;\n appPrice?: string;\n currency?: string;\n quantity: number;\n\n specs: VehicleExternalInfo;\n};\n\n/************\n *\n * Kanban\n */\n\nexport type OffersKanbanColumn = {\n status: string;\n results: SearchOffer[];\n totalCount: number;\n totalValue: string;\n};\n\nexport type MSearchOffersKanbanColumn = {\n column: OffersKanbanColumn;\n nextToken?: string;\n};\n\nexport type KanbanOffersSearchRequest = BaseSearchRequest & {\n nextTokens?: Record<string, string | undefined>;\n};\n\nexport type KanbanOffersNextList = Omit<\n NextList<OffersKanbanColumn, ReferenceData>,\n 'nextToken'\n> & {\n nextTokens?: Record<string, string | undefined>;\n};\n"]}
@@ -0,0 +1,11 @@
1
+ import { OfferStatus } from '../types/offers.js';
2
+ type CompareInput = {
3
+ currentStatus: OfferStatus;
4
+ referenceStatus: OfferStatus;
5
+ };
6
+ export declare const isSameOrAfterReferenceOfferStatus: (input: CompareInput) => boolean;
7
+ export declare const isAfterReferenceOfferStatus: (input: CompareInput) => boolean;
8
+ export declare const isSameOrBeforeReferenceOfferStatus: (input: CompareInput) => boolean;
9
+ export declare const isBeforeReferenceOfferStatus: (input: CompareInput) => boolean;
10
+ export {};
11
+ //# sourceMappingURL=offers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offers.d.ts","sourceRoot":"/","sources":["utils/offers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAoB,MAAM,oBAAoB,CAAC;AAEnE,KAAK,YAAY,GAAG;IAClB,aAAa,EAAE,WAAW,CAAC;IAC3B,eAAe,EAAE,WAAW,CAAC;CAC9B,CAAC;AAcF,eAAO,MAAM,iCAAiC,UAAW,YAAY,KAAG,OAIvE,CAAC;AAEF,eAAO,MAAM,2BAA2B,UAAW,YAAY,KAAG,OAIjE,CAAC;AAEF,eAAO,MAAM,kCAAkC,UAAW,YAAY,KAAG,OAIxE,CAAC;AAEF,eAAO,MAAM,4BAA4B,UAAW,YAAY,KAAG,OAIlE,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { OfferStatusOrder } from '../types/offers.js';
2
+ const compareOfferStatus = (input) => {
3
+ const { currentStatus, referenceStatus } = input;
4
+ const currentStatusIdx = OfferStatusOrder.indexOf(currentStatus);
5
+ const referenceStatusIdx = OfferStatusOrder.indexOf(referenceStatus);
6
+ return {
7
+ currentStatusIdx,
8
+ referenceStatusIdx,
9
+ };
10
+ };
11
+ export const isSameOrAfterReferenceOfferStatus = (input) => {
12
+ const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);
13
+ return currentStatusIdx >= referenceStatusIdx;
14
+ };
15
+ export const isAfterReferenceOfferStatus = (input) => {
16
+ const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);
17
+ return currentStatusIdx > referenceStatusIdx;
18
+ };
19
+ export const isSameOrBeforeReferenceOfferStatus = (input) => {
20
+ const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);
21
+ return currentStatusIdx <= referenceStatusIdx;
22
+ };
23
+ export const isBeforeReferenceOfferStatus = (input) => {
24
+ const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);
25
+ return currentStatusIdx < referenceStatusIdx;
26
+ };
27
+ //# sourceMappingURL=offers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offers.js","sourceRoot":"/","sources":["utils/offers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAOnE,MAAM,kBAAkB,GAAG,CAAC,KAAmB,EAAE,EAAE;IACjD,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,KAAK,CAAC;IAEjD,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAErE,OAAO;QACL,gBAAgB;QAChB,kBAAkB;KACnB,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,KAAmB,EAAW,EAAE;IAChF,MAAM,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAE3E,OAAO,gBAAgB,IAAI,kBAAkB,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,KAAmB,EAAW,EAAE;IAC1E,MAAM,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAE3E,OAAO,gBAAgB,GAAG,kBAAkB,CAAC;AAC/C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,KAAmB,EAAW,EAAE;IACjF,MAAM,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAE3E,OAAO,gBAAgB,IAAI,kBAAkB,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,KAAmB,EAAW,EAAE;IAC3E,MAAM,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAE3E,OAAO,gBAAgB,GAAG,kBAAkB,CAAC;AAC/C,CAAC,CAAC","sourcesContent":["import { OfferStatus, OfferStatusOrder } from '../types/offers.js';\n\ntype CompareInput = {\n currentStatus: OfferStatus;\n referenceStatus: OfferStatus;\n};\n\nconst compareOfferStatus = (input: CompareInput) => {\n const { currentStatus, referenceStatus } = input;\n\n const currentStatusIdx = OfferStatusOrder.indexOf(currentStatus);\n const referenceStatusIdx = OfferStatusOrder.indexOf(referenceStatus);\n\n return {\n currentStatusIdx,\n referenceStatusIdx,\n };\n};\n\nexport const isSameOrAfterReferenceOfferStatus = (input: CompareInput): boolean => {\n const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);\n\n return currentStatusIdx >= referenceStatusIdx;\n};\n\nexport const isAfterReferenceOfferStatus = (input: CompareInput): boolean => {\n const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);\n\n return currentStatusIdx > referenceStatusIdx;\n};\n\nexport const isSameOrBeforeReferenceOfferStatus = (input: CompareInput): boolean => {\n const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);\n\n return currentStatusIdx <= referenceStatusIdx;\n};\n\nexport const isBeforeReferenceOfferStatus = (input: CompareInput): boolean => {\n const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);\n\n return currentStatusIdx < referenceStatusIdx;\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bisondesk/core-sdk",
3
- "version": "1.0.368",
3
+ "version": "1.0.370",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "scripts": {
package/src/constants.ts CHANGED
@@ -14,6 +14,8 @@ export const VEHICLE_STATE_FILTERS_PICKLIST_ID = 'vehicleStateFilters';
14
14
  export const VEHICLE_SALE_DEAL_STATUS_PICKLIST_ID = 'vehicleSaleDealStatus';
15
15
  export const VEHICLE_ROLES_PICKLIST_ID = 'vehicleRoles';
16
16
  export const MARKETING_PLATFORMS_PICKLIST_ID = 'marketingPlatforms';
17
+ export const OFFER_STATUS_PICKLIST_ID = 'offerStatus';
18
+ export const OFFER_SOURCE_PICKLIST_ID = 'offerSource';
17
19
  export const OPPORTUNITY_STATUS_PICKLIST_ID = 'opportunityStatus';
18
20
  export const OPPORTUNITY_DEAL_STATUS_PICKLIST_ID = 'opportunityDealStatus';
19
21
  export const OPPORTUNITY_PAYMENT_STATUS_PICKLIST_ID = 'opportunityPaymentStatus';
package/src/types/crm.ts CHANGED
@@ -7,6 +7,14 @@ import {
7
7
  import { PublicSearchDefinition } from './definitions.js';
8
8
  import { ReferenceData } from './utils.js';
9
9
 
10
+ export enum OrganizatioRiskTags {
11
+ BAD_FINANCIAL_INFO = 'BAD_FINANCIAL_INFO',
12
+ VAT_NUMBER_INVALID = 'VAT_NUMBER_INVALID',
13
+ INSTINCT = 'INSTINCT',
14
+ NEW_CUSTOMER = 'NEW_CUSTOMER',
15
+ BANK_ACCOUNT_BLOCKED = 'BANK_ACCOUNT_BLOCKED',
16
+ }
17
+
10
18
  export type CrmEvent = CrmOrganizationEvent | CrmContactEvent;
11
19
 
12
20
  export type CrmContactEvent = {
@@ -8,6 +8,7 @@ export type SimilarVehiclesRequest = {
8
8
 
9
9
  export type InsightsSimilarRequest = {
10
10
  comparable: InsightsComparableSpecs;
11
+ excludeVehicleIds?: string[];
11
12
  limit: number;
12
13
  nextToken?: string;
13
14
  };
@@ -23,9 +24,7 @@ export type InsightsVehicleComparableResponse = {
23
24
  };
24
25
 
25
26
  // here we are considering only specs that we can use to filter Market vehicles
26
- export interface InsightsComparableSpecs extends ComparableSpecs {
27
- vehicleId: string;
28
- }
27
+ export interface InsightsComparableSpecs extends ComparableSpecs {}
29
28
 
30
29
  export type InsightsOptions = {
31
30
  months?: number;
@@ -0,0 +1,274 @@
1
+ import { DistributiveOmit, Document, NextList } from '@bisondesk/commons-sdk/types';
2
+ import { BusinessEntityIds, WarningHints } from '../constants.js';
3
+ import { Contact, Organization } from './crm.js';
4
+ import { Insights, InsightsComparableSpecs } from './insights.js';
5
+ import { ContactMetdata } from './opportunities.js';
6
+ import { BaseSearchRequest } from './search.js';
7
+ import { DataRecord, ReferenceData } from './utils.js';
8
+ import { VehicleExternalInfo } from './vehicles.js';
9
+
10
+ export enum OfferActions {
11
+ CREATE_BID = 'create_bid',
12
+ SET_FINAL_VALUATION = 'set_final_valuation',
13
+ LOSE = 'lose',
14
+ REOPEN = 'reopen',
15
+ SET_DOCUMENTS = 'set_documents',
16
+ SET_METADATA = 'set_metadata',
17
+ SEE_SUPPLIER = 'see_supplier',
18
+ SEE_INSIGHTS = 'see_insights',
19
+ VIEW_BIDS = 'view_bids',
20
+ SEE_ASKING_PRICE = 'see_asking_price',
21
+ ACCEPT_NEGOTIATION = 'accept_negotiation',
22
+ UNDO_ACCEPT_NEGOTIATION = 'undo_accept_negotiation',
23
+ SET_SUPPLIER_VEHICLE = 'set_supplier_vehicle',
24
+ }
25
+
26
+ export enum OfferBidActions {
27
+ EDIT_BID = 'create_bid',
28
+ DELETE_BID = 'delete_bid',
29
+ }
30
+
31
+ export enum OfferStatus {
32
+ PROSPECTION = 'prospection', // initial status
33
+ VALUATION = 'valuation', // has at least one internal or external bid with bid amount > 0
34
+ NEGOTIATION = 'negotiation', // there is a final valuation, purchaser is talking to the supplier
35
+ }
36
+
37
+ export enum OfferLostReasonValues {
38
+ Expensive = 'expensive',
39
+ NoMarket = 'no_market',
40
+ BadExperience = 'bad_experience',
41
+ NoAnswer = 'supplier_mia',
42
+ Automatic = 'automatic',
43
+ }
44
+
45
+ export enum OfferBidType {
46
+ INTERNAL = 'internal',
47
+ EXTERNAL = 'external',
48
+ }
49
+
50
+ export enum OfferWarningsCode {
51
+ NO_SUPPLIER = 'no_supplier',
52
+ }
53
+
54
+ export const OfferStatusOrder: OfferStatus[] = [
55
+ OfferStatus.PROSPECTION,
56
+ OfferStatus.VALUATION,
57
+ OfferStatus.NEGOTIATION,
58
+ ];
59
+
60
+ export const OfferWonColumnId = 'closed_won';
61
+
62
+ export const OfferKanbanColumns = [...OfferStatusOrder, OfferWonColumnId];
63
+
64
+ export const OfferKanbanEndColumns: string[] = [OfferWonColumnId];
65
+
66
+ type BaseOffer = {
67
+ branchId: string;
68
+ availableWeek?: string; // ISOWEEK, e.g. 2016-W02
69
+ askingPrice?: string;
70
+ currency?: string;
71
+ quantity: number;
72
+ specs: VehicleExternalInfo;
73
+ documents: Document[];
74
+ source?: string; // e.g., website, email, visit
75
+ contactId: string;
76
+ organizationId?: string;
77
+
78
+ supplierNotes?: string; // Optional notes from the supplier
79
+ };
80
+
81
+ export type NewOffer = BaseOffer & {
82
+ id?: undefined;
83
+ createdAt?: undefined;
84
+ createdBy?: undefined;
85
+ modifiedAt?: undefined;
86
+ modifiedBy?: undefined;
87
+ };
88
+
89
+ export type Offer = BaseOffer & {
90
+ id: string;
91
+ accountManager?: string; // optional since some offers might come directly from the internet
92
+ createdAt: string;
93
+ createdBy: string;
94
+ modifiedAt: string;
95
+ modifiedBy: string;
96
+ firstBidAt?: string;
97
+
98
+ lostReason?: OfferLostReasonValues;
99
+ status: OfferStatus;
100
+ quantity: number;
101
+
102
+ appPrice?: string;
103
+ appAvailability: boolean;
104
+
105
+ wonAt?: string;
106
+ wonBy?: string;
107
+ lostAt?: string;
108
+ lostBy?: string;
109
+
110
+ valuation?: { amount: string; valuationAt: string; valuationBy: string };
111
+
112
+ agreedAt?: string;
113
+ agreedBy?: string;
114
+ };
115
+
116
+ export type OfferUpdate = {
117
+ accountManager?: string | null;
118
+ branchId?: string | null;
119
+ supplierNotes?: string | null;
120
+ contactId?: string | null;
121
+ organizationId?: string | null;
122
+ lost?: boolean;
123
+ lostReason?: OfferLostReasonValues;
124
+ source?: string;
125
+ askingPrice?: string;
126
+ currency?: string;
127
+ quantity?: number;
128
+ specs?: VehicleExternalInfo;
129
+ addNewBid?: boolean;
130
+ documents?: Document[];
131
+ appAvailability?: boolean;
132
+
133
+ finalValuation?: string;
134
+ agreed?: boolean;
135
+ };
136
+
137
+ type OfferWarningActionLink = {
138
+ businessEntityId: BusinessEntityIds;
139
+ recordId: string;
140
+ };
141
+
142
+ type OfferWarningActionData = { [key: string]: string | number };
143
+
144
+ export type OfferWarning = {
145
+ code: OfferWarningsCode;
146
+ level: WarningHints;
147
+ link?: OfferWarningActionLink;
148
+ data?: OfferWarningActionData;
149
+ showAction?: boolean;
150
+ };
151
+
152
+ export type OfferMetadata = {
153
+ insights: {
154
+ online: Pick<Insights['online'], 'count' | 'percentilesDays' | 'percentilesPrices'>;
155
+ sold: Pick<Insights['sold'], 'count' | 'percentilesPrices' | 'percentilesDays'>;
156
+ };
157
+ stock: {
158
+ available: number;
159
+ leads: number;
160
+ };
161
+ comparable: InsightsComparableSpecs;
162
+ warnings: OfferWarning[];
163
+ };
164
+
165
+ export type OfferBff = {
166
+ offer: DataRecord<Offer, OfferMetadata>;
167
+ bids: DataRecord<OfferBid>[];
168
+ customer?: {
169
+ contact: DataRecord<Contact>;
170
+ org?: DataRecord<Organization>;
171
+ };
172
+ };
173
+
174
+ /************
175
+ *
176
+ * Bids
177
+ */
178
+
179
+ type BaseOfferBid = {
180
+ id: string;
181
+ createdAt: string;
182
+ createdBy: string;
183
+ modifiedAt: string;
184
+ modifiedBy: string;
185
+ offerId: string;
186
+ amount: string;
187
+ currency: string;
188
+ description?: string;
189
+ deleted: boolean;
190
+ };
191
+
192
+ export type InternalOfferBid = BaseOfferBid & {
193
+ userId: string;
194
+ final?: boolean; // Optional flag to indicate if this is the final valuation
195
+ type: OfferBidType.INTERNAL;
196
+ };
197
+
198
+ export type ExternalOfferBid = BaseOfferBid & {
199
+ contactId: string;
200
+ organizationId: string;
201
+ notes?: string;
202
+ type: OfferBidType.EXTERNAL;
203
+ };
204
+
205
+ export type OfferBid = InternalOfferBid | ExternalOfferBid;
206
+
207
+ export type NewOfferBid = DistributiveOmit<
208
+ OfferBid,
209
+ 'id' | 'createdAt' | 'createdBy' | 'modifiedAt' | 'modifiedBy' | 'deleted'
210
+ >;
211
+
212
+ export type InternalOfferBidUpdate = {
213
+ amount?: string | null;
214
+ currency?: string | null;
215
+ description?: string | null;
216
+ };
217
+
218
+ /************
219
+ *
220
+ * Search
221
+ */
222
+
223
+ export type SearchOffer = {
224
+ contact?: Contact;
225
+ offer: Offer;
226
+ org?: Organization;
227
+ custom: {
228
+ lost: boolean;
229
+ status: OfferStatus | 'won';
230
+ totalBids: number;
231
+ };
232
+ };
233
+
234
+ export type AppOffer = {
235
+ id: string;
236
+ branchId: string;
237
+ createdAt: string;
238
+ unavailableAt?: string;
239
+
240
+ availableWeek?: string;
241
+ appPrice?: string;
242
+ currency?: string;
243
+ quantity: number;
244
+
245
+ specs: VehicleExternalInfo;
246
+ };
247
+
248
+ /************
249
+ *
250
+ * Kanban
251
+ */
252
+
253
+ export type OffersKanbanColumn = {
254
+ status: string;
255
+ results: SearchOffer[];
256
+ totalCount: number;
257
+ totalValue: string;
258
+ };
259
+
260
+ export type MSearchOffersKanbanColumn = {
261
+ column: OffersKanbanColumn;
262
+ nextToken?: string;
263
+ };
264
+
265
+ export type KanbanOffersSearchRequest = BaseSearchRequest & {
266
+ nextTokens?: Record<string, string | undefined>;
267
+ };
268
+
269
+ export type KanbanOffersNextList = Omit<
270
+ NextList<OffersKanbanColumn, ReferenceData>,
271
+ 'nextToken'
272
+ > & {
273
+ nextTokens?: Record<string, string | undefined>;
274
+ };
@@ -0,0 +1,42 @@
1
+ import { OfferStatus, OfferStatusOrder } from '../types/offers.js';
2
+
3
+ type CompareInput = {
4
+ currentStatus: OfferStatus;
5
+ referenceStatus: OfferStatus;
6
+ };
7
+
8
+ const compareOfferStatus = (input: CompareInput) => {
9
+ const { currentStatus, referenceStatus } = input;
10
+
11
+ const currentStatusIdx = OfferStatusOrder.indexOf(currentStatus);
12
+ const referenceStatusIdx = OfferStatusOrder.indexOf(referenceStatus);
13
+
14
+ return {
15
+ currentStatusIdx,
16
+ referenceStatusIdx,
17
+ };
18
+ };
19
+
20
+ export const isSameOrAfterReferenceOfferStatus = (input: CompareInput): boolean => {
21
+ const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);
22
+
23
+ return currentStatusIdx >= referenceStatusIdx;
24
+ };
25
+
26
+ export const isAfterReferenceOfferStatus = (input: CompareInput): boolean => {
27
+ const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);
28
+
29
+ return currentStatusIdx > referenceStatusIdx;
30
+ };
31
+
32
+ export const isSameOrBeforeReferenceOfferStatus = (input: CompareInput): boolean => {
33
+ const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);
34
+
35
+ return currentStatusIdx <= referenceStatusIdx;
36
+ };
37
+
38
+ export const isBeforeReferenceOfferStatus = (input: CompareInput): boolean => {
39
+ const { currentStatusIdx, referenceStatusIdx } = compareOfferStatus(input);
40
+
41
+ return currentStatusIdx < referenceStatusIdx;
42
+ };