|
|
@@ -26,6 +26,10 @@ export interface DomesticCompetitorRelationRow extends DomesticProductRelation {
|
|
|
ownModel: string;
|
|
|
ownTitle: string;
|
|
|
ownProductAvailable: boolean;
|
|
|
+ competitorProduct?: DomesticProduct;
|
|
|
+ competitorModel: string;
|
|
|
+ competitorTitle: string;
|
|
|
+ competitorProductAvailable: boolean;
|
|
|
}
|
|
|
|
|
|
export interface DomesticOverview {
|
|
|
@@ -107,16 +111,17 @@ export class DomesticAnalyticsService {
|
|
|
|
|
|
readonly overview$ = this.dataset.dataset$.pipe(
|
|
|
map((dataset): DomesticOverview => {
|
|
|
+ const ownProducts = dataset.products.filter((product) => product.role === 'own');
|
|
|
const first = dataset.dailyTotals[0]?.gmv || 0;
|
|
|
const last = dataset.dailyTotals.at(-1)?.gmv || 0;
|
|
|
return {
|
|
|
dataset,
|
|
|
totals: aggregateDomesticMetrics(dataset.dailyTotals),
|
|
|
gmvTrend: first ? (last - first) / first : 0,
|
|
|
- topProducts: [...dataset.products]
|
|
|
+ topProducts: [...ownProducts]
|
|
|
.sort((a, b) => b.summary.gmv - a.summary.gmv || b.summary.soldUnits - a.summary.soldUnits)
|
|
|
.slice(0, 10),
|
|
|
- topCategories: buildDomesticCategorySummaries(dataset.products, 'category2').slice(0, 8),
|
|
|
+ topCategories: buildDomesticCategorySummaries(ownProducts, 'category2').slice(0, 8),
|
|
|
};
|
|
|
}),
|
|
|
shareReplay({ bufferSize: 1, refCount: false }),
|
|
|
@@ -124,8 +129,8 @@ export class DomesticAnalyticsService {
|
|
|
|
|
|
readonly categoryAnalysis$ = this.dataset.dataset$.pipe(
|
|
|
map((dataset): DomesticCategoryAnalysis => ({
|
|
|
- category2: buildDomesticCategorySummaries(dataset.products, 'category2'),
|
|
|
- category3: buildDomesticCategorySummaries(dataset.products, 'category3'),
|
|
|
+ category2: buildDomesticCategorySummaries(dataset.products.filter((product) => product.role === 'own'), 'category2'),
|
|
|
+ category3: buildDomesticCategorySummaries(dataset.products.filter((product) => product.role === 'own'), 'category3'),
|
|
|
relationCount: dataset.relations.length,
|
|
|
})),
|
|
|
shareReplay({ bufferSize: 1, refCount: false }),
|
|
|
@@ -147,6 +152,7 @@ export class DomesticAnalyticsService {
|
|
|
const mappingGroups = new Map(dataset.mappingGroups.map((group) => [group.ownProductId, group]));
|
|
|
return dataset.relations.map((relation) => {
|
|
|
const ownProduct = products.get(relation.ownProductId);
|
|
|
+ const competitorProduct = products.get(relation.competitorProductId);
|
|
|
const mapping = mappingGroups.get(relation.ownProductId);
|
|
|
return {
|
|
|
...relation,
|
|
|
@@ -154,6 +160,10 @@ export class DomesticAnalyticsService {
|
|
|
ownModel: ownProduct?.model || mapping?.model || relation.ownProductId,
|
|
|
ownTitle: ownProduct?.title || mapping?.model || relation.ownProductId,
|
|
|
ownProductAvailable: !!ownProduct,
|
|
|
+ competitorProduct,
|
|
|
+ competitorModel: competitorProduct?.model || relation.competitorProductId,
|
|
|
+ competitorTitle: competitorProduct?.title || relation.competitorBrand || relation.competitorProductId,
|
|
|
+ competitorProductAvailable: !!competitorProduct && competitorProduct.source === 'fmode_gateway' && Boolean(competitorProduct.title),
|
|
|
};
|
|
|
});
|
|
|
}),
|