@bprotsyk/aso-core 2.1.132 → 2.1.140
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.
- package/lib/app/app.d.ts +20 -16
- package/lib/app/app.js +5 -1
- package/lib/general/domain.d.ts +6 -2
- package/lib/general/domain.js +2 -1
- package/lib/general/namecheap-domain.d.ts +5 -5
- package/lib/keitaro/keitaro-conversions.d.ts +52 -0
- package/lib/keitaro/keitaro-conversions.js +27 -0
- package/lib/keitaro/keitaro-utils.d.ts +2 -0
- package/lib/keitaro/keitaro-utils.js +108 -0
- package/lib/keitaro-utils.d.ts +2 -0
- package/lib/keitaro-utils.js +136 -0
- package/lib/network/keitaro/traffle/traffle-keitaro-service.js +2 -3
- package/lib/offers/list.d.ts +5 -5
- package/lib/offers/offer.d.ts +6 -6
- package/lib/offers/section.d.ts +2 -2
- package/lib/panel/app/upsert-flash-app-request.d.ts +1 -0
- package/lib/panel/user.d.ts +5 -5
- package/lib/utils/comparing.d.ts +31 -0
- package/lib/utils/comparing.js +104 -0
- package/lib/utils/traffle-keitaro-utils.js +28 -38
- package/package.json +3 -1
- package/src/app/app.ts +6 -2
- package/src/general/domain.ts +3 -1
- package/src/network/keitaro/traffle/traffle-keitaro-service.ts +2 -3
- package/src/panel/app/upsert-flash-app-request.ts +1 -0
- package/src/utils/traffle-keitaro-utils.ts +12 -34
- package/lib/templates/words.txt +0 -212
- package/tsc +0 -0
package/lib/app/app.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ export interface IApp extends Document {
|
|
|
33
33
|
proxied: boolean;
|
|
34
34
|
ech?: boolean;
|
|
35
35
|
imageFormat: EImageFormat;
|
|
36
|
+
policyPath: string;
|
|
36
37
|
}
|
|
37
38
|
export declare enum EImageFormat {
|
|
38
39
|
PNG = "png",
|
|
@@ -197,18 +198,19 @@ export declare enum PlugType {
|
|
|
197
198
|
}
|
|
198
199
|
export declare const AppSchema: mongoose.Schema<any, mongoose.Model<any, any, any, any, any, any>, {}, {}, {}, {}, mongoose.DefaultSchemaOptions, {
|
|
199
200
|
id: number;
|
|
200
|
-
type:
|
|
201
|
+
type: AppType;
|
|
201
202
|
geo: string[];
|
|
202
203
|
enabled: boolean;
|
|
203
204
|
proxied: boolean;
|
|
204
205
|
ech: boolean;
|
|
205
|
-
imageFormat:
|
|
206
|
-
status:
|
|
207
|
-
team:
|
|
206
|
+
imageFormat: EImageFormat;
|
|
207
|
+
status: AppStatus;
|
|
208
|
+
team: ETeam;
|
|
208
209
|
bundle: string;
|
|
209
210
|
trackingUrl: string;
|
|
210
|
-
integrationVersion:
|
|
211
|
+
integrationVersion: IntegrationVersion;
|
|
211
212
|
removeInfo: any;
|
|
213
|
+
policyPath: string;
|
|
212
214
|
name?: string | null | undefined;
|
|
213
215
|
pushesEnabled?: boolean | null | undefined;
|
|
214
216
|
publicationHistory?: any;
|
|
@@ -240,18 +242,19 @@ export declare const AppSchema: mongoose.Schema<any, mongoose.Model<any, any, an
|
|
|
240
242
|
} | null | undefined;
|
|
241
243
|
}, mongoose.Document<unknown, {}, mongoose.FlatRecord<{
|
|
242
244
|
id: number;
|
|
243
|
-
type:
|
|
245
|
+
type: AppType;
|
|
244
246
|
geo: string[];
|
|
245
247
|
enabled: boolean;
|
|
246
248
|
proxied: boolean;
|
|
247
249
|
ech: boolean;
|
|
248
|
-
imageFormat:
|
|
249
|
-
status:
|
|
250
|
-
team:
|
|
250
|
+
imageFormat: EImageFormat;
|
|
251
|
+
status: AppStatus;
|
|
252
|
+
team: ETeam;
|
|
251
253
|
bundle: string;
|
|
252
254
|
trackingUrl: string;
|
|
253
|
-
integrationVersion:
|
|
255
|
+
integrationVersion: IntegrationVersion;
|
|
254
256
|
removeInfo: any;
|
|
257
|
+
policyPath: string;
|
|
255
258
|
name?: string | null | undefined;
|
|
256
259
|
pushesEnabled?: boolean | null | undefined;
|
|
257
260
|
publicationHistory?: any;
|
|
@@ -281,20 +284,21 @@ export declare const AppSchema: mongoose.Schema<any, mongoose.Model<any, any, an
|
|
|
281
284
|
name?: string | null | undefined;
|
|
282
285
|
clouflareZone?: string | null | undefined;
|
|
283
286
|
} | null | undefined;
|
|
284
|
-
}>> & mongoose.FlatRecord<{
|
|
287
|
+
}>, {}, mongoose.ResolveSchemaOptions<mongoose.DefaultSchemaOptions>> & mongoose.FlatRecord<{
|
|
285
288
|
id: number;
|
|
286
|
-
type:
|
|
289
|
+
type: AppType;
|
|
287
290
|
geo: string[];
|
|
288
291
|
enabled: boolean;
|
|
289
292
|
proxied: boolean;
|
|
290
293
|
ech: boolean;
|
|
291
|
-
imageFormat:
|
|
292
|
-
status:
|
|
293
|
-
team:
|
|
294
|
+
imageFormat: EImageFormat;
|
|
295
|
+
status: AppStatus;
|
|
296
|
+
team: ETeam;
|
|
294
297
|
bundle: string;
|
|
295
298
|
trackingUrl: string;
|
|
296
|
-
integrationVersion:
|
|
299
|
+
integrationVersion: IntegrationVersion;
|
|
297
300
|
removeInfo: any;
|
|
301
|
+
policyPath: string;
|
|
298
302
|
name?: string | null | undefined;
|
|
299
303
|
pushesEnabled?: boolean | null | undefined;
|
|
300
304
|
publicationHistory?: any;
|
package/lib/app/app.js
CHANGED
package/lib/general/domain.d.ts
CHANGED
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
/// <reference types="mongoose/types/populate" />
|
|
16
16
|
/// <reference types="mongoose/types/query" />
|
|
17
17
|
/// <reference types="mongoose/types/schemaoptions" />
|
|
18
|
-
/// <reference types="mongoose/types/schematypes" />
|
|
19
18
|
/// <reference types="mongoose/types/session" />
|
|
20
19
|
/// <reference types="mongoose/types/types" />
|
|
21
20
|
/// <reference types="mongoose/types/utility" />
|
|
22
21
|
/// <reference types="mongoose/types/validation" />
|
|
23
22
|
/// <reference types="mongoose/types/virtuals" />
|
|
23
|
+
/// <reference types="mongoose/types/schematypes" />
|
|
24
24
|
/// <reference types="mongoose/types/inferschematype" />
|
|
25
25
|
/// <reference types="mongoose/types/inferrawdoctype" />
|
|
26
26
|
import { ICloudflareDomainType } from "general/cloudflare-domain";
|
|
@@ -53,6 +53,7 @@ export interface IDomain extends Document {
|
|
|
53
53
|
note: string;
|
|
54
54
|
proxied: boolean;
|
|
55
55
|
appid: number;
|
|
56
|
+
expirationMessageSent?: boolean;
|
|
56
57
|
}
|
|
57
58
|
export interface IDomainsBuyRequestResponse {
|
|
58
59
|
requestId: string;
|
|
@@ -86,6 +87,7 @@ export declare const DomainSchema: Schema<any, Model<any, any, any, any, any, an
|
|
|
86
87
|
originalNameServers: string[];
|
|
87
88
|
txtRecords: string[];
|
|
88
89
|
assignedTo: number[];
|
|
90
|
+
expirationMessageSent: boolean;
|
|
89
91
|
id?: string | null | undefined;
|
|
90
92
|
name?: string | null | undefined;
|
|
91
93
|
type?: string | null | undefined;
|
|
@@ -113,6 +115,7 @@ export declare const DomainSchema: Schema<any, Model<any, any, any, any, any, an
|
|
|
113
115
|
originalNameServers: string[];
|
|
114
116
|
txtRecords: string[];
|
|
115
117
|
assignedTo: number[];
|
|
118
|
+
expirationMessageSent: boolean;
|
|
116
119
|
id?: string | null | undefined;
|
|
117
120
|
name?: string | null | undefined;
|
|
118
121
|
type?: string | null | undefined;
|
|
@@ -135,11 +138,12 @@ export declare const DomainSchema: Schema<any, Model<any, any, any, any, any, an
|
|
|
135
138
|
archived?: boolean | null | undefined;
|
|
136
139
|
note?: string | null | undefined;
|
|
137
140
|
appid?: number | null | undefined;
|
|
138
|
-
}>> & import("mongoose").FlatRecord<{
|
|
141
|
+
}>, {}, import("mongoose").ResolveSchemaOptions<import("mongoose").DefaultSchemaOptions>> & import("mongoose").FlatRecord<{
|
|
139
142
|
nameServers: string[];
|
|
140
143
|
originalNameServers: string[];
|
|
141
144
|
txtRecords: string[];
|
|
142
145
|
assignedTo: number[];
|
|
146
|
+
expirationMessageSent: boolean;
|
|
143
147
|
id?: string | null | undefined;
|
|
144
148
|
name?: string | null | undefined;
|
|
145
149
|
type?: string | null | undefined;
|
package/lib/general/domain.js
CHANGED
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
/// <reference types="mongoose/types/populate" />
|
|
16
16
|
/// <reference types="mongoose/types/query" />
|
|
17
17
|
/// <reference types="mongoose/types/schemaoptions" />
|
|
18
|
-
/// <reference types="mongoose/types/schematypes" />
|
|
19
18
|
/// <reference types="mongoose/types/session" />
|
|
20
19
|
/// <reference types="mongoose/types/types" />
|
|
21
20
|
/// <reference types="mongoose/types/utility" />
|
|
22
21
|
/// <reference types="mongoose/types/validation" />
|
|
23
22
|
/// <reference types="mongoose/types/virtuals" />
|
|
23
|
+
/// <reference types="mongoose/types/schematypes" />
|
|
24
24
|
/// <reference types="mongoose/types/inferschematype" />
|
|
25
25
|
/// <reference types="mongoose/types/inferrawdoctype" />
|
|
26
26
|
import { Schema, Document } from "mongoose";
|
|
@@ -79,7 +79,7 @@ export declare const NamecheapBuyRequestSchema: Schema<any, import("mongoose").M
|
|
|
79
79
|
name?: string | null | undefined;
|
|
80
80
|
price?: number | null | undefined;
|
|
81
81
|
available?: boolean | null | undefined;
|
|
82
|
-
}, import("mongoose").Types.Subdocument<import("
|
|
82
|
+
}, import("mongoose").Types.Subdocument<import("bson").ObjectId, any, {
|
|
83
83
|
name?: string | null | undefined;
|
|
84
84
|
price?: number | null | undefined;
|
|
85
85
|
available?: boolean | null | undefined;
|
|
@@ -96,7 +96,7 @@ export declare const NamecheapBuyRequestSchema: Schema<any, import("mongoose").M
|
|
|
96
96
|
name?: string | null | undefined;
|
|
97
97
|
price?: number | null | undefined;
|
|
98
98
|
available?: boolean | null | undefined;
|
|
99
|
-
}, import("mongoose").Types.Subdocument<import("
|
|
99
|
+
}, import("mongoose").Types.Subdocument<import("bson").ObjectId, any, {
|
|
100
100
|
name?: string | null | undefined;
|
|
101
101
|
price?: number | null | undefined;
|
|
102
102
|
available?: boolean | null | undefined;
|
|
@@ -108,12 +108,12 @@ export declare const NamecheapBuyRequestSchema: Schema<any, import("mongoose").M
|
|
|
108
108
|
id?: string | null | undefined;
|
|
109
109
|
ip?: string | null | undefined;
|
|
110
110
|
fullfilled?: boolean | null | undefined;
|
|
111
|
-
}>> & import("mongoose").FlatRecord<{
|
|
111
|
+
}>, {}, import("mongoose").ResolveSchemaOptions<import("mongoose").DefaultSchemaOptions>> & import("mongoose").FlatRecord<{
|
|
112
112
|
domains: import("mongoose").Types.DocumentArray<{
|
|
113
113
|
name?: string | null | undefined;
|
|
114
114
|
price?: number | null | undefined;
|
|
115
115
|
available?: boolean | null | undefined;
|
|
116
|
-
}, import("mongoose").Types.Subdocument<import("
|
|
116
|
+
}, import("mongoose").Types.Subdocument<import("bson").ObjectId, any, {
|
|
117
117
|
name?: string | null | undefined;
|
|
118
118
|
price?: number | null | undefined;
|
|
119
119
|
available?: boolean | null | undefined;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { KeitaroClicksInterval } from './keitaro-clicks';
|
|
2
|
+
export declare enum KeitaroOperator {
|
|
3
|
+
EQUALS = "EQUALS",
|
|
4
|
+
NOT_EQUAL = "NOT_EQUAL",
|
|
5
|
+
EQUALS_OR_GREATER_THAN = "EQUALS_OR_GREATER_THAN",
|
|
6
|
+
EQUALS_OR_LESS_THAN = "EQUALS_OR_LESS_THAN",
|
|
7
|
+
GREATER_THAN = "GREATER_THAN",
|
|
8
|
+
LESS_THAN = "LESS_THAN",
|
|
9
|
+
MATCH_REGEXP = "MATCH_REGEXP",
|
|
10
|
+
NOT_MATCH_REGEXP = "NOT_MATCH_REGEXP",
|
|
11
|
+
BEGINS_WITH = "BEGINS_WITH",
|
|
12
|
+
ENDS_WITH = "ENDS_WITH",
|
|
13
|
+
CONTAINS = "CONTAINS",
|
|
14
|
+
NOT_CONTAIN = "NOT_CONTAIN",
|
|
15
|
+
IN_LIST = "IN_LIST",
|
|
16
|
+
NOT_IN_LIST = "NOT_IN_LIST",
|
|
17
|
+
BETWEEN = "BETWEEN",
|
|
18
|
+
IS_SET = "IS_SET",
|
|
19
|
+
IS_NOT_SET = "IS_NOT_SET",
|
|
20
|
+
IS_TRUE = "IS_TRUE",
|
|
21
|
+
IS_FALSE = "IS_FALSE",
|
|
22
|
+
HAS_LABEL = "HAS_LABEL",
|
|
23
|
+
NOT_HAS_LABEL = "NOT_HAS_LABEL"
|
|
24
|
+
}
|
|
25
|
+
export interface IKeitaroConversionRangeRequest {
|
|
26
|
+
from?: string;
|
|
27
|
+
to?: string;
|
|
28
|
+
timezone?: string;
|
|
29
|
+
interval?: KeitaroClicksInterval;
|
|
30
|
+
}
|
|
31
|
+
export interface IKeitaroConversionFilterRequest {
|
|
32
|
+
name: string;
|
|
33
|
+
operator: KeitaroOperator;
|
|
34
|
+
expression?: string | number | Array<string | number>;
|
|
35
|
+
}
|
|
36
|
+
export interface IKeitaroConversionSortRequest {
|
|
37
|
+
name: string;
|
|
38
|
+
order: 'ASC' | 'DESC';
|
|
39
|
+
}
|
|
40
|
+
export interface IKeitaroConversionsRequest {
|
|
41
|
+
range: IKeitaroConversionRangeRequest;
|
|
42
|
+
limit?: number;
|
|
43
|
+
offset?: number;
|
|
44
|
+
columns?: string[];
|
|
45
|
+
filters?: IKeitaroConversionFilterRequest[];
|
|
46
|
+
sort?: IKeitaroConversionSortRequest[];
|
|
47
|
+
}
|
|
48
|
+
export interface IKeitaroConversionsResponse {
|
|
49
|
+
rows: any[];
|
|
50
|
+
total: number;
|
|
51
|
+
meta: string[];
|
|
52
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KeitaroOperator = void 0;
|
|
4
|
+
var KeitaroOperator;
|
|
5
|
+
(function (KeitaroOperator) {
|
|
6
|
+
KeitaroOperator["EQUALS"] = "EQUALS";
|
|
7
|
+
KeitaroOperator["NOT_EQUAL"] = "NOT_EQUAL";
|
|
8
|
+
KeitaroOperator["EQUALS_OR_GREATER_THAN"] = "EQUALS_OR_GREATER_THAN";
|
|
9
|
+
KeitaroOperator["EQUALS_OR_LESS_THAN"] = "EQUALS_OR_LESS_THAN";
|
|
10
|
+
KeitaroOperator["GREATER_THAN"] = "GREATER_THAN";
|
|
11
|
+
KeitaroOperator["LESS_THAN"] = "LESS_THAN";
|
|
12
|
+
KeitaroOperator["MATCH_REGEXP"] = "MATCH_REGEXP";
|
|
13
|
+
KeitaroOperator["NOT_MATCH_REGEXP"] = "NOT_MATCH_REGEXP";
|
|
14
|
+
KeitaroOperator["BEGINS_WITH"] = "BEGINS_WITH";
|
|
15
|
+
KeitaroOperator["ENDS_WITH"] = "ENDS_WITH";
|
|
16
|
+
KeitaroOperator["CONTAINS"] = "CONTAINS";
|
|
17
|
+
KeitaroOperator["NOT_CONTAIN"] = "NOT_CONTAIN";
|
|
18
|
+
KeitaroOperator["IN_LIST"] = "IN_LIST";
|
|
19
|
+
KeitaroOperator["NOT_IN_LIST"] = "NOT_IN_LIST";
|
|
20
|
+
KeitaroOperator["BETWEEN"] = "BETWEEN";
|
|
21
|
+
KeitaroOperator["IS_SET"] = "IS_SET";
|
|
22
|
+
KeitaroOperator["IS_NOT_SET"] = "IS_NOT_SET";
|
|
23
|
+
KeitaroOperator["IS_TRUE"] = "IS_TRUE";
|
|
24
|
+
KeitaroOperator["IS_FALSE"] = "IS_FALSE";
|
|
25
|
+
KeitaroOperator["HAS_LABEL"] = "HAS_LABEL";
|
|
26
|
+
KeitaroOperator["NOT_HAS_LABEL"] = "NOT_HAS_LABEL";
|
|
27
|
+
})(KeitaroOperator = exports.KeitaroOperator || (exports.KeitaroOperator = {}));
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.displayComparisonResults = void 0;
|
|
4
|
+
function displayComparisonResults(comparison) {
|
|
5
|
+
const isValidStatus = (status) => ['sale', 'rebill'].includes(status);
|
|
6
|
+
let wpTotalSum = comparison.wpConversions
|
|
7
|
+
.reduce((sum, conv) => sum + conv.sum, 0);
|
|
8
|
+
let keitaroTotalSum = comparison.keitaroConversions
|
|
9
|
+
.filter(conv => isValidStatus(conv.status))
|
|
10
|
+
.reduce((sum, conv) => sum + (parseFloat(conv.revenue) || 0), 0);
|
|
11
|
+
// Get all Keitaro rejected conversions
|
|
12
|
+
const allKeitaroRejected = [
|
|
13
|
+
...comparison.rejected.keitaro,
|
|
14
|
+
...comparison.matches
|
|
15
|
+
.filter(match => match.keitaro.status === 'rejected')
|
|
16
|
+
.map(match => match.keitaro)
|
|
17
|
+
];
|
|
18
|
+
// Group mismatches by project/offer
|
|
19
|
+
const wpMismatchesByProject = new Map();
|
|
20
|
+
const keitaroMismatchesByOffer = new Map();
|
|
21
|
+
const rejectedByOffer = new Map();
|
|
22
|
+
comparison.mismatches.onlyInWP.forEach(conv => {
|
|
23
|
+
if (!wpMismatchesByProject.has(conv.project)) {
|
|
24
|
+
wpMismatchesByProject.set(conv.project, { count: 0, sum: 0, conversions: [] });
|
|
25
|
+
}
|
|
26
|
+
const projectStats = wpMismatchesByProject.get(conv.project);
|
|
27
|
+
projectStats.count++;
|
|
28
|
+
projectStats.sum += conv.sum;
|
|
29
|
+
projectStats.conversions.push(conv);
|
|
30
|
+
});
|
|
31
|
+
// Include all conversions in mismatches, including rejected ones
|
|
32
|
+
[...comparison.mismatches.onlyInKeitaro, ...allKeitaroRejected].forEach(conv => {
|
|
33
|
+
if (!keitaroMismatchesByOffer.has(conv.offer)) {
|
|
34
|
+
keitaroMismatchesByOffer.set(conv.offer, { count: 0, sum: 0, conversions: [] });
|
|
35
|
+
}
|
|
36
|
+
const offerStats = keitaroMismatchesByOffer.get(conv.offer);
|
|
37
|
+
offerStats.count++;
|
|
38
|
+
offerStats.sum += parseFloat(conv.revenue) || 0;
|
|
39
|
+
offerStats.conversions.push(conv);
|
|
40
|
+
});
|
|
41
|
+
// Group rejected conversions by offer
|
|
42
|
+
allKeitaroRejected.forEach(conv => {
|
|
43
|
+
if (!rejectedByOffer.has(conv.offer)) {
|
|
44
|
+
rejectedByOffer.set(conv.offer, { count: 0, sum: 0, conversions: [] });
|
|
45
|
+
}
|
|
46
|
+
const offerStats = rejectedByOffer.get(conv.offer);
|
|
47
|
+
offerStats.count++;
|
|
48
|
+
offerStats.sum += parseFloat(conv.revenue) || 0;
|
|
49
|
+
offerStats.conversions.push(conv);
|
|
50
|
+
});
|
|
51
|
+
console.log('\n\x1b[1mЗагальна статистика:\x1b[0m');
|
|
52
|
+
console.log(`Всього конверсій у WP: ${comparison.wpConversions.length} (Сума: \x1b[33m$${wpTotalSum.toFixed(2)}\x1b[0m)`);
|
|
53
|
+
console.log(`Всього конверсій у Keitaro: ${comparison.keitaroConversions.filter(conv => isValidStatus(conv.status)).length} (Сума: \x1b[33m$${keitaroTotalSum.toFixed(2)}\x1b[0m)`);
|
|
54
|
+
console.log(`Співпадінь: ${comparison.matches.length}`);
|
|
55
|
+
console.log(`Відхилених конверсій: ${allKeitaroRejected.length}`);
|
|
56
|
+
const totalDiff = Math.abs(wpTotalSum - keitaroTotalSum);
|
|
57
|
+
console.log(`\x1b[1mЗагальна різниця:\x1b[0m \x1b[33m$${totalDiff.toFixed(2)}\x1b[0m`);
|
|
58
|
+
// Always show rejected conversions first if there are any
|
|
59
|
+
if (allKeitaroRejected.length > 0) {
|
|
60
|
+
const rejectedTotal = allKeitaroRejected.reduce((sum, conv) => sum + (parseFloat(conv.revenue) || 0), 0);
|
|
61
|
+
console.log('\n\x1b[1mВідхилені конверсії в Keitaro за офферами:\x1b[0m');
|
|
62
|
+
console.log(`Загальна кількість: ${allKeitaroRejected.length}`);
|
|
63
|
+
console.log(`Загальна сума: \x1b[33m$${rejectedTotal.toFixed(2)}\x1b[0m`);
|
|
64
|
+
for (const [offer, stats] of rejectedByOffer.entries()) {
|
|
65
|
+
console.log(`\n\x1b[33m${offer}:\x1b[0m`);
|
|
66
|
+
console.log(`Кількість: ${stats.count}, Сума: $${stats.sum.toFixed(2)}`);
|
|
67
|
+
stats.conversions.forEach(conv => {
|
|
68
|
+
const matchMark = comparison.matches.some(match => match.keitaro.sub_id === conv.sub_id) ? '[matched] ' : '';
|
|
69
|
+
console.log(` ${matchMark}${conv.sub_id} | ${conv.sale_datetime.split(' ')[0]} | $${conv.revenue}`);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
console.log('\n\x1b[1mВідсутні в Keitaro за проектами:\x1b[0m');
|
|
74
|
+
for (const [project, stats] of wpMismatchesByProject) {
|
|
75
|
+
console.log(`\n\x1b[31m${project}:\x1b[0m`);
|
|
76
|
+
console.log(`Кількість: ${stats.count}, Сума: $${stats.sum.toFixed(2)}`);
|
|
77
|
+
stats.conversions.forEach(conv => {
|
|
78
|
+
console.log(` ${conv.clickId} | ${conv.regDate.toISOString().split('T')[0]} | $${conv.sum}`);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
console.log('\n\x1b[1mВідсутні в WP за офферами:\x1b[0m');
|
|
82
|
+
for (const [offer, stats] of keitaroMismatchesByOffer) {
|
|
83
|
+
console.log(`\n\x1b[32m${offer}:\x1b[0m`);
|
|
84
|
+
console.log(`Кількість: ${stats.count}, Сума: $${stats.sum.toFixed(2)}`);
|
|
85
|
+
stats.conversions.forEach(conv => {
|
|
86
|
+
const statusMark = conv.status === 'rejected' ? '(rejected) ' : '';
|
|
87
|
+
const matchMark = comparison.matches.some(match => match.keitaro.sub_id === conv.sub_id) ? '[matched] ' : '';
|
|
88
|
+
console.log(` ${statusMark}${matchMark}${conv.sub_id} | ${conv.sale_datetime.split(' ')[0]} | $${conv.revenue}`);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
let mismatchWPSum = comparison.mismatches.onlyInWP
|
|
92
|
+
.reduce((sum, conv) => sum + conv.sum, 0);
|
|
93
|
+
let mismatchKeitaroSum = [...comparison.mismatches.onlyInKeitaro, ...allKeitaroRejected]
|
|
94
|
+
.reduce((sum, conv) => sum + (parseFloat(conv.revenue) || 0), 0);
|
|
95
|
+
console.log('\n\x1b[1mПідсумок розбіжностей:\x1b[0m');
|
|
96
|
+
console.log(`Сума відсутніх в Keitaro: \x1b[31m$${mismatchWPSum.toFixed(2)}\x1b[0m`);
|
|
97
|
+
console.log(`Сума відсутніх в WP: \x1b[32m$${mismatchKeitaroSum.toFixed(2)}\x1b[0m`);
|
|
98
|
+
console.log(`Різниця у відсутніх конверсіях: \x1b[33m$${Math.abs(mismatchWPSum - mismatchKeitaroSum).toFixed(2)}\x1b[0m`);
|
|
99
|
+
// Debug information
|
|
100
|
+
const matchingRejected = comparison.matches.filter(match => match.keitaro.status === 'rejected').length;
|
|
101
|
+
console.log('\n\x1b[1mДебаг інформація:\x1b[0m');
|
|
102
|
+
console.log(`Кількість конверсій відсутніх в WP: ${comparison.mismatches.onlyInKeitaro.length + comparison.rejected.keitaro.length + matchingRejected}`);
|
|
103
|
+
console.log(`З них:`);
|
|
104
|
+
console.log(`- Активних: ${comparison.mismatches.onlyInKeitaro.length}`);
|
|
105
|
+
console.log(`- Відхилених (унікальних): ${comparison.rejected.keitaro.length}`);
|
|
106
|
+
console.log(`- Відхилених (що є в WP): ${matchingRejected}`);
|
|
107
|
+
}
|
|
108
|
+
exports.displayComparisonResults = displayComparisonResults;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.displayComparisonResults = void 0;
|
|
27
|
+
const keitaro_service_1 = require("./network/keitaro/keitaro-service");
|
|
28
|
+
const keitaro_conversions_1 = require("./keitaro/keitaro-conversions");
|
|
29
|
+
const path = __importStar(require("path"));
|
|
30
|
+
const comparing_1 = require("./utils/comparing");
|
|
31
|
+
function displayComparisonResults(comparison) {
|
|
32
|
+
const isValidStatus = (status) => ['sale', 'rebill'].includes(status);
|
|
33
|
+
// Считаем общие суммы
|
|
34
|
+
let wpTotalSum = comparison.wpConversions
|
|
35
|
+
.reduce((sum, conv) => sum + conv.sum, 0);
|
|
36
|
+
let keitaroTotalSum = comparison.keitaroConversions
|
|
37
|
+
.filter((conv) => isValidStatus(conv.status))
|
|
38
|
+
.reduce((sum, conv) => sum + (parseFloat(conv.revenue) || 0), 0);
|
|
39
|
+
// Находим разницу
|
|
40
|
+
const totalDiff = keitaroTotalSum - wpTotalSum;
|
|
41
|
+
console.log('\n\x1b[1mЗагальна статистика:\x1b[0m');
|
|
42
|
+
console.log(`WP сума: $${wpTotalSum.toFixed(2)}`);
|
|
43
|
+
console.log(`Keitaro сума: $${keitaroTotalSum.toFixed(2)}`);
|
|
44
|
+
console.log(`Різниця: $${totalDiff.toFixed(2)}`);
|
|
45
|
+
// Получаем конверсии, которые есть в Keitaro, но нет в WP
|
|
46
|
+
const extraKeitaroConversions = comparison.mismatches.onlyInKeitaro
|
|
47
|
+
.filter(conv => isValidStatus(conv.status))
|
|
48
|
+
.sort((a, b) => (parseFloat(b.revenue) || 0) - (parseFloat(a.revenue) || 0));
|
|
49
|
+
// Группируем по офферам для удобства
|
|
50
|
+
const byOffer = new Map();
|
|
51
|
+
extraKeitaroConversions.forEach(conv => {
|
|
52
|
+
const offer = conv.offer || 'Unknown Offer';
|
|
53
|
+
if (!byOffer.has(offer)) {
|
|
54
|
+
byOffer.set(offer, { count: 0, sum: 0, conversions: [] });
|
|
55
|
+
}
|
|
56
|
+
const stats = byOffer.get(offer);
|
|
57
|
+
const revenue = parseFloat(conv.revenue) || 0;
|
|
58
|
+
stats.count++;
|
|
59
|
+
stats.sum += revenue;
|
|
60
|
+
stats.conversions.push(conv);
|
|
61
|
+
});
|
|
62
|
+
console.log('\n\x1b[1mКонверсії, які є в Keitaro, але відсутні в WP:\x1b[0m');
|
|
63
|
+
let totalExtraSum = 0;
|
|
64
|
+
for (const [offer, stats] of byOffer) {
|
|
65
|
+
console.log(`\n\x1b[33m${offer}:\x1b[0m`);
|
|
66
|
+
console.log(`Кількість: ${stats.count}, Сума: $${stats.sum.toFixed(2)}`);
|
|
67
|
+
stats.conversions.forEach(conv => {
|
|
68
|
+
if (conv.sub_id && conv.revenue) {
|
|
69
|
+
console.log(` ${conv.sub_id} | ${conv.revenue}`);
|
|
70
|
+
totalExtraSum += parseFloat(conv.revenue) || 0;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
console.log('\n\x1b[1mПідсумок:\x1b[0m');
|
|
75
|
+
console.log(`Загальна сума "зайвих" конверсій: \x1b[33m$${totalExtraSum.toFixed(2)}\x1b[0m`);
|
|
76
|
+
console.log('Це конверсії, які потрібно видалити з Keitaro, щоб суми співпадали з WP');
|
|
77
|
+
}
|
|
78
|
+
exports.displayComparisonResults = displayComparisonResults;
|
|
79
|
+
// Self-executing function to fetch and compare conversions
|
|
80
|
+
(async () => {
|
|
81
|
+
const request = {
|
|
82
|
+
range: {
|
|
83
|
+
from: '2025-01-01',
|
|
84
|
+
to: '2025-01-31',
|
|
85
|
+
timezone: 'Europe/Kyiv'
|
|
86
|
+
},
|
|
87
|
+
filters: [
|
|
88
|
+
{
|
|
89
|
+
name: 'status',
|
|
90
|
+
operator: keitaro_conversions_1.KeitaroOperator.IN_LIST,
|
|
91
|
+
expression: ['sale', 'rejected']
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: 'affiliate_network_id',
|
|
95
|
+
operator: keitaro_conversions_1.KeitaroOperator.EQUALS,
|
|
96
|
+
expression: 2
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
columns: [
|
|
100
|
+
'sign', 'version', 'campaign', 'campaign_group', 'landing_group', 'offer_group',
|
|
101
|
+
'landing', 'offer', 'affiliate_network', 'ts', 'stream', 'source',
|
|
102
|
+
'x_requested_with', 'referrer', 'search_engine', 'keyword', 'click_id',
|
|
103
|
+
'sub_id', 'visitor_code', 'campaign_id', 'campaign_group_id', 'offer_group_id',
|
|
104
|
+
'landing_group_id', 'landing_id', 'offer_id', 'affiliate_network_id', 'ts_id',
|
|
105
|
+
'stream_id', 'ad_campaign_id', 'external_id', 'creative_id',
|
|
106
|
+
'sub_id_1', 'sub_id_2', 'sub_id_3', 'sub_id_4', 'sub_id_5',
|
|
107
|
+
'sub_id_6', 'sub_id_7', 'sub_id_8', 'sub_id_9', 'sub_id_10',
|
|
108
|
+
'sub_id_11', 'sub_id_12', 'sub_id_13', 'sub_id_14', 'sub_id_15',
|
|
109
|
+
'sub_id_16', 'sub_id_17', 'sub_id_18', 'sub_id_19', 'sub_id_20',
|
|
110
|
+
'sub_id_21', 'sub_id_22', 'sub_id_23', 'sub_id_24', 'sub_id_25',
|
|
111
|
+
'sub_id_26', 'sub_id_27', 'sub_id_28', 'sub_id_29', 'sub_id_30',
|
|
112
|
+
'connection_type', 'operator', 'isp', 'country_code', 'country_flag',
|
|
113
|
+
'country', 'region', 'region_code', 'city', 'language', 'device_type',
|
|
114
|
+
'user_agent', 'os_icon', 'os', 'os_version', 'browser', 'browser_version',
|
|
115
|
+
'device_model', 'browser_icon', 'ip', 'ip_mask1', 'ip_mask2', 'ipv4only',
|
|
116
|
+
'ipv6only', 'cost', 'postback_datetime', 'sale_datetime', 'click_datetime',
|
|
117
|
+
'sale_period', 'status', 'previous_status', 'original_status',
|
|
118
|
+
'previous_conversion_id', 'params', 'conversion_id', 'tid',
|
|
119
|
+
'profitability', 'revenue', 'profit'
|
|
120
|
+
],
|
|
121
|
+
sort: [{
|
|
122
|
+
name: 'sale_datetime',
|
|
123
|
+
order: 'DESC'
|
|
124
|
+
}]
|
|
125
|
+
};
|
|
126
|
+
try {
|
|
127
|
+
const conversions = await keitaro_service_1.KeitaroService.getConversions(request);
|
|
128
|
+
const wpFilePath = path.join(process.cwd(), 'src', 'utils', 'wp-january.csv');
|
|
129
|
+
const comparison = await (0, comparing_1.compareConversions)(wpFilePath, conversions);
|
|
130
|
+
// Use our improved display function
|
|
131
|
+
displayComparisonResults(comparison);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.error('Error fetching conversions:', error);
|
|
135
|
+
}
|
|
136
|
+
})();
|
|
@@ -151,7 +151,7 @@ async function addOffersToTraffleKeitaro(offers) {
|
|
|
151
151
|
let name = `${offer.offer.caption} ${offer.offer.geo} [el trafico] ${offer.trafficType}`;
|
|
152
152
|
const identicalOffer = allOffers.find(o => o.name.includes(name));
|
|
153
153
|
let offersGroupId = findMatchingOffersGroup(offersGroups, offer);
|
|
154
|
-
let affiliateId = await findMatchingAffiliateId(affiliateNetworks, offer)
|
|
154
|
+
let affiliateId = 160; // await findMatchingAffiliateId(affiliateNetworks, offer)
|
|
155
155
|
if (!identicalOffer) {
|
|
156
156
|
const offerPayload = {
|
|
157
157
|
name: name,
|
|
@@ -467,8 +467,7 @@ async function updateAppWithCampaignParams(existingCampaign, app, platform) {
|
|
|
467
467
|
async function cloneTraffleCampaign(app, platform, addDefaultStreams) {
|
|
468
468
|
const ORIGINAL_CLONE_CAMPAIGN_ID = 1925;
|
|
469
469
|
const appsflyerAvailability = app.platforms[platform].appsflyerParams?.apiToken ? "[AF]" : "";
|
|
470
|
-
|
|
471
|
-
let name = `[${app.id}] [${app.bundle}] ET [${app.name}] [Volodymyr Vinnik] [Android] ${appsflyerAvailability} ${app.domainParams.name}`;
|
|
470
|
+
let name = `[${app.id}] [${app.bundle}] ${app.name} [Volodymyr Vinnik] [El Trafico] [Android] ${appsflyerAvailability} ${app.domainParams.name}`;
|
|
472
471
|
let platformName = platform ? (0, app_1.getPlatformName)(platform) : null;
|
|
473
472
|
const platformCampaignName = `#${app.id} [➥] (${platformName})`;
|
|
474
473
|
const generateAlias = () => {
|
package/lib/offers/list.d.ts
CHANGED
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
/// <reference types="mongoose/types/populate" />
|
|
16
16
|
/// <reference types="mongoose/types/query" />
|
|
17
17
|
/// <reference types="mongoose/types/schemaoptions" />
|
|
18
|
-
/// <reference types="mongoose/types/schematypes" />
|
|
19
18
|
/// <reference types="mongoose/types/session" />
|
|
20
19
|
/// <reference types="mongoose/types/types" />
|
|
21
20
|
/// <reference types="mongoose/types/utility" />
|
|
22
21
|
/// <reference types="mongoose/types/validation" />
|
|
23
22
|
/// <reference types="mongoose/types/virtuals" />
|
|
23
|
+
/// <reference types="mongoose/types/schematypes" />
|
|
24
24
|
/// <reference types="mongoose/types/inferschematype" />
|
|
25
25
|
/// <reference types="mongoose/types/inferrawdoctype" />
|
|
26
26
|
import { Schema } from "mongoose";
|
|
@@ -85,7 +85,7 @@ export declare const SectionsListSchema: Schema<any, import("mongoose").Model<an
|
|
|
85
85
|
getOwnPropertyDescriptors?: {} | null | undefined;
|
|
86
86
|
fromEntries?: {} | null | undefined;
|
|
87
87
|
hasOwn?: {} | null | undefined;
|
|
88
|
-
}, import("mongoose").Types.Subdocument<import("
|
|
88
|
+
}, import("mongoose").Types.Subdocument<import("bson").ObjectId, any, {
|
|
89
89
|
prototype?: {
|
|
90
90
|
constructor: {
|
|
91
91
|
name?: unknown;
|
|
@@ -218,7 +218,7 @@ export declare const SectionsListSchema: Schema<any, import("mongoose").Model<an
|
|
|
218
218
|
getOwnPropertyDescriptors?: {} | null | undefined;
|
|
219
219
|
fromEntries?: {} | null | undefined;
|
|
220
220
|
hasOwn?: {} | null | undefined;
|
|
221
|
-
}, import("mongoose").Types.Subdocument<import("
|
|
221
|
+
}, import("mongoose").Types.Subdocument<import("bson").ObjectId, any, {
|
|
222
222
|
prototype?: {
|
|
223
223
|
constructor: {
|
|
224
224
|
name?: unknown;
|
|
@@ -305,7 +305,7 @@ export declare const SectionsListSchema: Schema<any, import("mongoose").Model<an
|
|
|
305
305
|
fromEntries?: {} | null | undefined;
|
|
306
306
|
hasOwn?: {} | null | undefined;
|
|
307
307
|
}>;
|
|
308
|
-
}>> & import("mongoose").FlatRecord<{
|
|
308
|
+
}>, {}, import("mongoose").ResolveSchemaOptions<import("mongoose").DefaultSchemaOptions>> & import("mongoose").FlatRecord<{
|
|
309
309
|
id: number;
|
|
310
310
|
name: string;
|
|
311
311
|
content: import("mongoose").Types.DocumentArray<{
|
|
@@ -351,7 +351,7 @@ export declare const SectionsListSchema: Schema<any, import("mongoose").Model<an
|
|
|
351
351
|
getOwnPropertyDescriptors?: {} | null | undefined;
|
|
352
352
|
fromEntries?: {} | null | undefined;
|
|
353
353
|
hasOwn?: {} | null | undefined;
|
|
354
|
-
}, import("mongoose").Types.Subdocument<import("
|
|
354
|
+
}, import("mongoose").Types.Subdocument<import("bson").ObjectId, any, {
|
|
355
355
|
prototype?: {
|
|
356
356
|
constructor: {
|
|
357
357
|
name?: unknown;
|