Skip to content

Commit 8bc3b49

Browse files
authored
Merge pull request #22 from ThePiratePhone/add-priority-for-client
Add priority for client
2 parents c5cab7a + 0241578 commit 8bc3b49

30 files changed

+680
-99
lines changed

Models/Campaign.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,15 @@ const CampaignSchema = new mongoose.Schema({
6767
{ name: 'À rappeler', toRecall: true },
6868
{ name: 'À retirer', toRecall: false }
6969
]
70+
},
71+
sortGroup: {
72+
type: [{ name: String, id: String }],
73+
required: true,
74+
default: [
75+
{ name: 'prio1', id: 'md4rye5b' },
76+
{ name: 'prio2', id: 'md4ryvjl' },
77+
{ name: 'default', id: '-1' }
78+
]
7079
}
7180
});
7281

Models/Client.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ const ClientSchema = new mongoose.Schema({
2929
required: true,
3030
default: []
3131
},
32+
priority: {
33+
type: [
34+
{
35+
campaign: mongoose.Schema.ObjectId,
36+
id: String
37+
}
38+
],
39+
required: false,
40+
default: []
41+
},
3242
createdAt: {
3343
type: Date,
3444
default: Date.now()

router/admin/campaign/GetCampaign.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { checkParameters, hashPasword } from '../../../tools/utils';
1212
* body:{
1313
* "adminCode": string,
1414
* "area": mongoDBID,
15-
* "CampaignId": mongoDBID,
15+
* "CampaignId"?: mongoDBID,
1616
* "allreadyHaseded": boolean
1717
* }
1818
*
@@ -34,7 +34,7 @@ export default async function getCampaign(req: Request<any>, res: Response<any>)
3434
res,
3535
[
3636
['adminCode', 'string'],
37-
['CampaignId', 'string'],
37+
['CampaignId', 'string', true],
3838
['area', 'ObjectId'],
3939
['allreadyHaseded', 'boolean', true]
4040
],
@@ -51,7 +51,8 @@ export default async function getCampaign(req: Request<any>, res: Response<any>)
5151
log(`[!${req.body.area}, ${ip}] Wrong admin code`, 'WARNING', __filename);
5252
return;
5353
}
54-
const campaign = await Campaign.findOne({ area: area._id, _id: { $eq: req.body.CampaignId } }, [
54+
let campaign: any = null;
55+
let returnType = [
5556
'_id',
5657
'name',
5758
'active',
@@ -63,14 +64,27 @@ export default async function getCampaign(req: Request<any>, res: Response<any>)
6364
'callPermited',
6465
'nbMaxCallCampaign',
6566
'satisfactions',
66-
'status'
67-
]);
67+
'status',
68+
'sortGroup'
69+
];
70+
if (req.body.CampaignId) {
71+
campaign = await Campaign.findOne({ _id: { $eq: req.body.CampaignId }, area: area._id }, returnType);
72+
} else {
73+
campaign = await Campaign.findOne({ area: area._id, active: true }, returnType);
74+
}
6875
if (!campaign) {
6976
res.status(404).send({ message: 'no campaign', OK: false });
7077
log(`[${ip}, ${req.body.area}] no campaign`, 'WARNING', __filename);
7178
return;
7279
}
7380

74-
res.status(200).send({ message: 'OK', OK: true, data: campaign });
81+
//remove last priority, it's internal used
82+
campaign.sortGroup.pop();
83+
84+
res.status(200).send({
85+
message: 'OK',
86+
OK: true,
87+
data: campaign
88+
});
7589
log(`[${ip}, ${req.body.area}] list campaign`, 'INFO', __filename);
7690
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { Request, Response } from 'express';
2+
3+
import { Area } from '../../../Models/Area';
4+
import { Campaign } from '../../../Models/Campaign';
5+
import { log } from '../../../tools/log';
6+
import { checkParameters, hashPasword, sanitizeString } from '../../../tools/utils';
7+
8+
/**
9+
* Set the priority of a campaign
10+
*
11+
* @example
12+
* body:{
13+
* "adminCode": string,
14+
* "priority": Array<{ name: string, id: string(length = 8) }>,
15+
* "area": mongoDBID,
16+
* "CampaignId": mongoDBID,
17+
* "allreadyHaseded": boolean
18+
* }
19+
*
20+
* @throws {400} - Missing parameters
21+
* @throws {400} - bad hash for admin code
22+
* @throws {400} - Invalid priority, priority must be a array<{ name: string, id: string(length = 8) }>
23+
* @throws {401} - Wrong admin code
24+
* @throws {401} - Wrong campaign id
25+
* @throws {200} - OK
26+
*/
27+
export default async function setPriority(req: Request<any>, res: Response<any>) {
28+
const ip =
29+
(Array.isArray(req.headers['x-forwarded-for'])
30+
? req.headers['x-forwarded-for'][0]
31+
: req.headers['x-forwarded-for']?.split(',')?.[0] ?? req.ip) ?? 'no IP';
32+
if (
33+
!checkParameters(
34+
req.body,
35+
res,
36+
[
37+
['adminCode', 'string'],
38+
['area', 'ObjectId'],
39+
['CampaignId', 'string', true],
40+
['allreadyHaseded', 'boolean', true]
41+
],
42+
__filename
43+
)
44+
)
45+
return;
46+
47+
if (!req.body.priority || !Array.isArray(req.body.priority)) {
48+
res.status(400).send({
49+
message: 'Invalid priority, priority must be a array<{ name: string, id: string(length = 8) }>',
50+
OK: false
51+
});
52+
log(`[!${req.body.area}, ${ip}] Invalid priority`, 'WARNING', __filename);
53+
return;
54+
}
55+
56+
const password = hashPasword(req.body.adminCode, req.body.allreadyHaseded, res);
57+
if (!password) return;
58+
const area = await Area.findOne({ _id: { $eq: req.body.area }, adminPassword: { $eq: password } });
59+
if (!area) {
60+
res.status(401).send({ message: 'Wrong admin code', OK: false });
61+
log(`[!${req.body.area}, ${ip}] Wrong admin code`, 'WARNING', __filename);
62+
return;
63+
}
64+
65+
let campaign: InstanceType<typeof Campaign> | null = null;
66+
67+
if (req.body.CampaignId) {
68+
campaign = await Campaign.findOne({ _id: { $eq: req.body.CampaignId }, area: area._id }, [
69+
'_id',
70+
'name',
71+
'sortGroup'
72+
]);
73+
} else {
74+
campaign = await Campaign.findOne({ area: area._id, active: true }, ['_id', 'name', 'sortGroup']);
75+
}
76+
if (!campaign) {
77+
res.status(401).send({ message: 'Wrong campaign id', OK: false });
78+
log(`[${req.body.area}, ${ip}] Wrong campaign id`, 'WARNING', __filename);
79+
return;
80+
}
81+
82+
if (
83+
!req.body.priority.every(
84+
(e: any) => typeof e?.name === 'string' && typeof e?.id === 'string' && (e?.id.length == 8 || e?.id == '-1')
85+
)
86+
) {
87+
res.status(400).send({
88+
message: 'Invalid priority, priority must be a array<{ name: string, id: string(length = 8) }>',
89+
OK: false
90+
});
91+
log(`[${req.body.area}, ${ip}] Invalid priority`, 'WARNING', __filename);
92+
return;
93+
}
94+
95+
const priority = req.body.priority.map((e: any) => ({
96+
name: sanitizeString(e.name),
97+
id: e.id
98+
}));
99+
priority.push({ name: 'default', id: '-1' });
100+
101+
await Campaign.updateOne({ _id: campaign._id }, { sortGroup: priority });
102+
res.status(200).send({ message: 'Priority updated', OK: true });
103+
log(`[${req.body.area}, ${ip}] Priority updated for ${campaign.name}`, 'INFO', __filename);
104+
}

router/admin/campaign/setSatisfaction.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ import { checkParameters, hashPasword, sanitizeString } from '../../../tools/uti
1111
* @example
1212
* body:{
1313
* "adminCode": string,
14-
* "satisfactions": string[],
14+
* "satisfactions": Array<{ name: string, toRecall: boolean }>,
1515
* "area": mongoDBID,
1616
* "CampaignId": mongoDBID,
1717
* "allreadyHaseded": boolean
1818
* }
1919
*
2020
* @throws {400} - Missing parameters
2121
* @throws {400} - bad hash for admin code
22-
* @throws {400} - Invalid satisfaction satisfactions must be a array<string>
22+
* @throws {400} - Invalid satisfaction satisfactions must be a array<{ name: string, toRecall: boolean }>
2323
* @throws {401} - Wrong admin code
2424
* @throws {401} - Wrong campaign id
2525
* @throws {200} - OK
@@ -88,5 +88,5 @@ export default async function setSatisfaction(req: Request<any>, res: Response<a
8888

8989
await Campaign.updateOne({ _id: campaign._id }, { status: req.body.satisfactions });
9090
res.status(200).send({ message: 'Satisfaction updated', OK: true });
91-
log(`[${req.body.area}, ${ip}] Satisfaction updated from`, 'INFO', __filename);
91+
log(`[${req.body.area}, ${ip}] Satisfaction updated for ${campaign.name}`, 'INFO', __filename);
9292
}

router/admin/client/clientInfo.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ export default async function clientInfo(req: Request<any>, res: Response<any>)
9292
'satisfaction',
9393
'status',
9494
'start',
95-
'comment'
95+
'comment',
96+
'priority'
9697
]);
9798
if (!call || call.length === 0) {
9899
res.status(200).send({

router/admin/client/createClient.ts

Lines changed: 83 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
import { Request, Response } from 'express';
22

33
import { Area } from '../../../Models/Area';
4+
import { Campaign } from '../../../Models/Campaign';
45
import { Client } from '../../../Models/Client';
56
import { log } from '../../../tools/log';
67
import { checkParameters, clearPhone, hashPasword, phoneNumberCheck, sanitizeString } from '../../../tools/utils';
78

89
/**
910
* create a client
11+
* if this client is updated, the updateKey value is reqired
1012
*
1113
* @example
1214
* body:{
1315
* phone: string,
1416
* name: string,
1517
* adminCode: string,
1618
* pinCode: string,
17-
* area: string,
19+
* area: ObjectId,
1820
* "allreadyHased": boolean
21+
* firstName?: string,
22+
* institution?: string,
23+
* updateIfExist?: boolean,
24+
* updateKey: ObjectId
1925
* }
2026
*
2127
* @throws {400} if missing parameters
@@ -43,14 +49,37 @@ export default async function createClient(req: Request<any>, res: Response<any>
4349
['institution', 'string', true],
4450
['adminCode', 'string'],
4551
['area', 'ObjectId'],
46-
['allreadyHaseded', 'boolean', true]
52+
['allreadyHaseded', 'boolean', true],
53+
['updateIfExist', 'boolean', true],
54+
['updateKey', 'ObjectId', true]
4755
],
4856
__filename
4957
)
5058
)
5159
return;
5260
const password = hashPasword(req.body.adminCode, req.body.allreadyHaseded, res);
5361
if (!password) return;
62+
63+
if (
64+
req.body.priority &&
65+
(!Array.isArray(req.body.priority) ||
66+
req.body.priority.every(
67+
(e: any) =>
68+
!e.campaign ||
69+
!e.id ||
70+
typeof e.campaign !== 'string' ||
71+
typeof e.id !== 'string' ||
72+
(e.id.length != 8 && e.id != '-1') // Allow '-1' for default priority
73+
))
74+
) {
75+
res.status(400).send({
76+
message: 'Invalid priority, priority must be a array<{ campaign: objectId, id: string(lenght=8) }>',
77+
OK: false
78+
});
79+
log(`[!${req.body.area}, ${ip}] Invalid priority`, 'WARNING', __filename);
80+
return;
81+
}
82+
5483
const area = await Area.findOne({ adminPassword: { $eq: password }, _id: { $eq: req.body.area } });
5584
if (!area) {
5685
res.status(401).send({ message: 'Wrong admin code', OK: false });
@@ -65,24 +94,64 @@ export default async function createClient(req: Request<any>, res: Response<any>
6594
return;
6695
}
6796

68-
if ((await Client.findOne({ phone: phone })) != null) {
69-
res.status(401).send({ message: 'User already exist', OK: false });
97+
const exist = (await Client.findOne({ phone: phone })) != null;
98+
if (!req.body.updateIfExist && exist) {
99+
res.status(422).send({ message: 'User already exist', OK: false });
70100
log(`[${req.body.area}, ${ip}] User already exist`, 'WARNING', __filename);
71101
return;
72102
}
73103

74-
const user = new Client({
75-
name: sanitizeString(req.body.name),
76-
phone: phone,
77-
firstName: sanitizeString(req.body.firstName ?? ''),
78-
institution: sanitizeString(req.body.institution ?? ''),
79-
area: area._id
80-
});
104+
const campaign = await Campaign.findOne({ area: { $eq: area._id }, active: true }, []);
105+
if (!campaign) {
106+
res.status(404).send({ message: 'no campaign in progress', OK: false });
107+
log(`[${req.body.area}, ${ip}] no campaign in progress`, 'WARNING', __filename);
108+
return;
109+
}
110+
111+
let client: InstanceType<typeof Client>;
112+
if (exist) {
113+
if ((await Client.countDocuments({ phone, _id: { $not: { $eq: req.body.updateKey } } })) != 0) {
114+
res.status(422).send({ message: 'phone number already exist', OK: false });
115+
log(`[${req.body.area}, ${ip}] phone number already exist`, 'WARNING', __filename);
116+
return;
117+
}
118+
const client = await Client.updateOne(
119+
{ _id: req.body.updateKey },
120+
{
121+
name: sanitizeString(req.body.name),
122+
phone: phone,
123+
firstName: sanitizeString(req.body.firstName ?? ''),
124+
institution: sanitizeString(req.body.institution ?? ''),
125+
area: area._id,
126+
campaigns: [campaign._id],
127+
priority: req.body.priority ?? [{ campaign: campaign._id, id: '-1' }]
128+
}
129+
);
130+
if (client.modifiedCount === 0) {
131+
res.status(404).send({ message: 'Client not found', OK: false });
132+
log(`[${req.body.area}, ${ip}] Client not found`, 'WARNING', __filename);
133+
return;
134+
} else {
135+
res.status(200).send({ message: 'Client updated', OK: true });
136+
log(`[${req.body.area}, ${ip}] Client updated`, 'INFO', __filename);
137+
return;
138+
}
139+
} else {
140+
client = new Client({
141+
name: sanitizeString(req.body.name),
142+
phone: phone,
143+
firstName: sanitizeString(req.body.firstName ?? ''),
144+
institution: sanitizeString(req.body.institution ?? ''),
145+
area: area._id,
146+
campaigns: [campaign._id],
147+
priority: req.body.priority ?? [{ campaign: campaign._id, id: '-1' }]
148+
});
149+
}
81150

82151
try {
83-
await user.save();
84-
res.status(200).send({ message: 'user ' + user.name + ' created', OK: true });
85-
log(`[${req.body.area}, ${ip}] user ${user.name} created`, 'INFO', __filename);
152+
await client.save();
153+
res.status(200).send({ message: 'client ' + client.name + ' created', OK: true });
154+
log(`[${req.body.area}, ${ip}] client ${client.name} created`, 'INFO', __filename);
86155
} catch (error: any) {
87156
res.status(500).send({ message: 'Internal server error', OK: false });
88157
log(`[${req.body.area}, ${ip}] Internal server error: ${error.message}`, 'ERROR', __filename);

0 commit comments

Comments
 (0)