@iservice365/module-hygiene 1.0.3 → 1.1.0
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/CHANGELOG.md +6 -0
- package/dist/index.d.ts +73 -12
- package/dist/index.js +624 -182
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +629 -178
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -644,7 +644,7 @@ function useAreaController() {
|
|
|
644
644
|
return;
|
|
645
645
|
}
|
|
646
646
|
const page = parseInt(req.query.page) ?? 1;
|
|
647
|
-
const limit = parseInt(req.query.limit) ??
|
|
647
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
648
648
|
const search = req.query.search ?? "";
|
|
649
649
|
const site = req.params.site ?? "";
|
|
650
650
|
try {
|
|
@@ -1193,7 +1193,7 @@ function useUnitController() {
|
|
|
1193
1193
|
return;
|
|
1194
1194
|
}
|
|
1195
1195
|
const page = parseInt(req.query.page) ?? 1;
|
|
1196
|
-
const limit = parseInt(req.query.limit) ??
|
|
1196
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
1197
1197
|
const search = req.query.search ?? "";
|
|
1198
1198
|
const site = req.params.site ?? "";
|
|
1199
1199
|
try {
|
|
@@ -1607,7 +1607,7 @@ function useParentChecklistController() {
|
|
|
1607
1607
|
return;
|
|
1608
1608
|
}
|
|
1609
1609
|
const page = parseInt(req.query.page) ?? 1;
|
|
1610
|
-
const limit = parseInt(req.query.limit) ??
|
|
1610
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
1611
1611
|
const search = req.query.search ?? "";
|
|
1612
1612
|
const site = req.params.site ?? "";
|
|
1613
1613
|
const startDate = req.query.startDate ?? "";
|
|
@@ -2626,7 +2626,7 @@ function useAreaChecklistController() {
|
|
|
2626
2626
|
return;
|
|
2627
2627
|
}
|
|
2628
2628
|
const page = parseInt(req.query.page) ?? 1;
|
|
2629
|
-
const limit = parseInt(req.query.limit) ??
|
|
2629
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
2630
2630
|
const search = req.query.search ?? "";
|
|
2631
2631
|
const type = req.query.type ?? "";
|
|
2632
2632
|
const schedule = req.params.schedule ?? "";
|
|
@@ -2664,7 +2664,7 @@ function useAreaChecklistController() {
|
|
|
2664
2664
|
return;
|
|
2665
2665
|
}
|
|
2666
2666
|
const page = parseInt(req.query.page) ?? 1;
|
|
2667
|
-
const limit = parseInt(req.query.limit) ??
|
|
2667
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
2668
2668
|
const search = req.query.search ?? "";
|
|
2669
2669
|
const type = req.query.type ?? "";
|
|
2670
2670
|
const schedule = req.params.schedule ?? "";
|
|
@@ -2722,7 +2722,7 @@ function useAreaChecklistController() {
|
|
|
2722
2722
|
return;
|
|
2723
2723
|
}
|
|
2724
2724
|
const page = parseInt(req.query.page) ?? 1;
|
|
2725
|
-
const limit = parseInt(req.query.limit) ??
|
|
2725
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
2726
2726
|
const search = req.query.search ?? "";
|
|
2727
2727
|
const _id = req.params.id ?? "";
|
|
2728
2728
|
try {
|
|
@@ -2797,8 +2797,7 @@ import { ObjectId as ObjectId9 } from "mongodb";
|
|
|
2797
2797
|
var supplySchema = Joi9.object({
|
|
2798
2798
|
site: Joi9.string().hex().required(),
|
|
2799
2799
|
name: Joi9.string().required(),
|
|
2800
|
-
unitOfMeasurement: Joi9.string().required()
|
|
2801
|
-
qty: Joi9.number().min(0).required()
|
|
2800
|
+
unitOfMeasurement: Joi9.string().required()
|
|
2802
2801
|
});
|
|
2803
2802
|
function MSupply(value) {
|
|
2804
2803
|
const { error } = supplySchema.validate(value);
|
|
@@ -2817,7 +2816,7 @@ function MSupply(value) {
|
|
|
2817
2816
|
site: value.site,
|
|
2818
2817
|
name: value.name,
|
|
2819
2818
|
unitOfMeasurement: value.unitOfMeasurement,
|
|
2820
|
-
qty:
|
|
2819
|
+
qty: 0,
|
|
2821
2820
|
status: "active",
|
|
2822
2821
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2823
2822
|
updatedAt: "",
|
|
@@ -2952,7 +2951,7 @@ function useSupplyRepository() {
|
|
|
2952
2951
|
throw error;
|
|
2953
2952
|
}
|
|
2954
2953
|
}
|
|
2955
|
-
async function getSupplyById(_id) {
|
|
2954
|
+
async function getSupplyById(_id, session) {
|
|
2956
2955
|
try {
|
|
2957
2956
|
_id = new ObjectId10(_id);
|
|
2958
2957
|
} catch (error) {
|
|
@@ -2965,10 +2964,14 @@ function useSupplyRepository() {
|
|
|
2965
2964
|
const cacheKey = makeCacheKey5(namespace_collection, {
|
|
2966
2965
|
_id: _id.toString()
|
|
2967
2966
|
});
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2967
|
+
if (!session) {
|
|
2968
|
+
const cachedData = await getCache(cacheKey);
|
|
2969
|
+
if (cachedData) {
|
|
2970
|
+
logger17.info(`Cache hit for key: ${cacheKey}`);
|
|
2971
|
+
return cachedData;
|
|
2972
|
+
}
|
|
2973
|
+
} else {
|
|
2974
|
+
logger17.info(`Skipping cache during transaction for key: ${cacheKey}`);
|
|
2972
2975
|
}
|
|
2973
2976
|
try {
|
|
2974
2977
|
const data = await collection.aggregate([
|
|
@@ -3072,39 +3075,172 @@ function useSupplyRepository() {
|
|
|
3072
3075
|
};
|
|
3073
3076
|
}
|
|
3074
3077
|
|
|
3075
|
-
// src/
|
|
3076
|
-
import { useAtlas as useAtlas9 } from "@iservice365/node-server-utils";
|
|
3077
|
-
|
|
3078
|
-
// src/models/hygiene-stock.model.ts
|
|
3078
|
+
// src/controllers/hygiene-supply.controller.ts
|
|
3079
3079
|
import { BadRequestError as BadRequestError17, logger as logger18 } from "@iservice365/node-server-utils";
|
|
3080
3080
|
import Joi10 from "joi";
|
|
3081
|
+
function useSupplyController() {
|
|
3082
|
+
const {
|
|
3083
|
+
createSupply: _createSupply,
|
|
3084
|
+
getSupplies: _getSupplies,
|
|
3085
|
+
getSupplyById: _getSupplyById,
|
|
3086
|
+
updateSupply: _updateSupply,
|
|
3087
|
+
deleteSupply: _deleteSupply
|
|
3088
|
+
} = useSupplyRepository();
|
|
3089
|
+
async function createSupply(req, res, next) {
|
|
3090
|
+
const payload = { ...req.body, ...req.params };
|
|
3091
|
+
const { error } = supplySchema.validate(payload);
|
|
3092
|
+
if (error) {
|
|
3093
|
+
logger18.log({ level: "error", message: error.message });
|
|
3094
|
+
next(new BadRequestError17(error.message));
|
|
3095
|
+
return;
|
|
3096
|
+
}
|
|
3097
|
+
try {
|
|
3098
|
+
const id = await _createSupply(payload);
|
|
3099
|
+
res.status(201).json({ message: "Supply created successfully.", id });
|
|
3100
|
+
return;
|
|
3101
|
+
} catch (error2) {
|
|
3102
|
+
logger18.log({ level: "error", message: error2.message });
|
|
3103
|
+
next(error2);
|
|
3104
|
+
return;
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
async function getSupplies(req, res, next) {
|
|
3108
|
+
const query = { ...req.query, ...req.params };
|
|
3109
|
+
const validation = Joi10.object({
|
|
3110
|
+
page: Joi10.number().min(1).optional().allow("", null),
|
|
3111
|
+
limit: Joi10.number().min(1).optional().allow("", null),
|
|
3112
|
+
search: Joi10.string().optional().allow("", null),
|
|
3113
|
+
site: Joi10.string().hex().required()
|
|
3114
|
+
});
|
|
3115
|
+
const { error } = validation.validate(query);
|
|
3116
|
+
if (error) {
|
|
3117
|
+
logger18.log({ level: "error", message: error.message });
|
|
3118
|
+
next(new BadRequestError17(error.message));
|
|
3119
|
+
return;
|
|
3120
|
+
}
|
|
3121
|
+
const page = parseInt(req.query.page) ?? 1;
|
|
3122
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
3123
|
+
const search = req.query.search ?? "";
|
|
3124
|
+
const site = req.params.site ?? "";
|
|
3125
|
+
try {
|
|
3126
|
+
const data = await _getSupplies({
|
|
3127
|
+
page,
|
|
3128
|
+
limit,
|
|
3129
|
+
search,
|
|
3130
|
+
site
|
|
3131
|
+
});
|
|
3132
|
+
res.json(data);
|
|
3133
|
+
return;
|
|
3134
|
+
} catch (error2) {
|
|
3135
|
+
logger18.log({ level: "error", message: error2.message });
|
|
3136
|
+
next(error2);
|
|
3137
|
+
return;
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
async function getSupplyById(req, res, next) {
|
|
3141
|
+
const validation = Joi10.string().hex().required();
|
|
3142
|
+
const _id = req.params.id;
|
|
3143
|
+
const { error } = validation.validate(_id);
|
|
3144
|
+
if (error) {
|
|
3145
|
+
logger18.log({ level: "error", message: error.message });
|
|
3146
|
+
next(new BadRequestError17(error.message));
|
|
3147
|
+
return;
|
|
3148
|
+
}
|
|
3149
|
+
try {
|
|
3150
|
+
const data = await _getSupplyById(_id);
|
|
3151
|
+
res.json(data);
|
|
3152
|
+
return;
|
|
3153
|
+
} catch (error2) {
|
|
3154
|
+
logger18.log({ level: "error", message: error2.message });
|
|
3155
|
+
next(error2);
|
|
3156
|
+
return;
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
async function updateSupply(req, res, next) {
|
|
3160
|
+
const payload = { id: req.params.id, ...req.body };
|
|
3161
|
+
const validation = Joi10.object({
|
|
3162
|
+
id: Joi10.string().hex().required(),
|
|
3163
|
+
name: Joi10.string().optional().allow("", null),
|
|
3164
|
+
unitOfMeasurement: Joi10.string().optional().allow("", null),
|
|
3165
|
+
qty: Joi10.number().min(0).optional().allow("", null)
|
|
3166
|
+
});
|
|
3167
|
+
const { error } = validation.validate(payload);
|
|
3168
|
+
if (error) {
|
|
3169
|
+
logger18.log({ level: "error", message: error.message });
|
|
3170
|
+
next(new BadRequestError17(error.message));
|
|
3171
|
+
return;
|
|
3172
|
+
}
|
|
3173
|
+
try {
|
|
3174
|
+
const { id, ...value } = payload;
|
|
3175
|
+
await _updateSupply(id, value);
|
|
3176
|
+
res.json({ message: "Supply updated successfully." });
|
|
3177
|
+
return;
|
|
3178
|
+
} catch (error2) {
|
|
3179
|
+
logger18.log({ level: "error", message: error2.message });
|
|
3180
|
+
next(error2);
|
|
3181
|
+
return;
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3184
|
+
async function deleteSupply(req, res, next) {
|
|
3185
|
+
const id = req.params.id;
|
|
3186
|
+
const validation = Joi10.object({
|
|
3187
|
+
id: Joi10.string().hex().required()
|
|
3188
|
+
});
|
|
3189
|
+
const { error } = validation.validate({ id });
|
|
3190
|
+
if (error) {
|
|
3191
|
+
logger18.log({ level: "error", message: error.message });
|
|
3192
|
+
next(new BadRequestError17(error.message));
|
|
3193
|
+
return;
|
|
3194
|
+
}
|
|
3195
|
+
try {
|
|
3196
|
+
await _deleteSupply(id);
|
|
3197
|
+
res.json({ message: "Supply deleted successfully." });
|
|
3198
|
+
return;
|
|
3199
|
+
} catch (error2) {
|
|
3200
|
+
logger18.log({ level: "error", message: error2.message });
|
|
3201
|
+
next(error2);
|
|
3202
|
+
return;
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
3205
|
+
return {
|
|
3206
|
+
createSupply,
|
|
3207
|
+
getSupplies,
|
|
3208
|
+
getSupplyById,
|
|
3209
|
+
updateSupply,
|
|
3210
|
+
deleteSupply
|
|
3211
|
+
};
|
|
3212
|
+
}
|
|
3213
|
+
|
|
3214
|
+
// src/models/hygiene-stock.model.ts
|
|
3215
|
+
import { BadRequestError as BadRequestError18, logger as logger19 } from "@iservice365/node-server-utils";
|
|
3216
|
+
import Joi11 from "joi";
|
|
3081
3217
|
import { ObjectId as ObjectId11 } from "mongodb";
|
|
3082
|
-
var stockSchema =
|
|
3083
|
-
site:
|
|
3084
|
-
supply:
|
|
3085
|
-
in:
|
|
3086
|
-
out:
|
|
3087
|
-
balance:
|
|
3088
|
-
remarks:
|
|
3218
|
+
var stockSchema = Joi11.object({
|
|
3219
|
+
site: Joi11.string().hex().required(),
|
|
3220
|
+
supply: Joi11.string().hex().required(),
|
|
3221
|
+
in: Joi11.number().min(0).optional(),
|
|
3222
|
+
out: Joi11.number().min(0).optional(),
|
|
3223
|
+
balance: Joi11.number().min(0).required(),
|
|
3224
|
+
remarks: Joi11.string().optional().allow("", null)
|
|
3089
3225
|
});
|
|
3090
3226
|
function MStock(value) {
|
|
3091
3227
|
const { error } = stockSchema.validate(value);
|
|
3092
3228
|
if (error) {
|
|
3093
|
-
|
|
3094
|
-
throw new
|
|
3229
|
+
logger19.info(`Hygiene Stock Model: ${error.message}`);
|
|
3230
|
+
throw new BadRequestError18(error.message);
|
|
3095
3231
|
}
|
|
3096
3232
|
if (value.site) {
|
|
3097
3233
|
try {
|
|
3098
3234
|
value.site = new ObjectId11(value.site);
|
|
3099
3235
|
} catch (error2) {
|
|
3100
|
-
throw new
|
|
3236
|
+
throw new BadRequestError18("Invalid site ID format.");
|
|
3101
3237
|
}
|
|
3102
3238
|
}
|
|
3103
3239
|
if (value.supply) {
|
|
3104
3240
|
try {
|
|
3105
3241
|
value.supply = new ObjectId11(value.supply);
|
|
3106
3242
|
} catch (error2) {
|
|
3107
|
-
throw new
|
|
3243
|
+
throw new BadRequestError18("Invalid supply ID format.");
|
|
3108
3244
|
}
|
|
3109
3245
|
}
|
|
3110
3246
|
return {
|
|
@@ -3122,12 +3258,15 @@ function MStock(value) {
|
|
|
3122
3258
|
}
|
|
3123
3259
|
|
|
3124
3260
|
// src/repositories/hygiene-stock.repository.ts
|
|
3261
|
+
import { ObjectId as ObjectId12 } from "mongodb";
|
|
3125
3262
|
import {
|
|
3126
3263
|
useAtlas as useAtlas8,
|
|
3127
3264
|
InternalServerError as InternalServerError6,
|
|
3128
|
-
BadRequestError as
|
|
3265
|
+
BadRequestError as BadRequestError19,
|
|
3129
3266
|
useCache as useCache6,
|
|
3130
|
-
logger as
|
|
3267
|
+
logger as logger20,
|
|
3268
|
+
makeCacheKey as makeCacheKey6,
|
|
3269
|
+
paginate as paginate6
|
|
3131
3270
|
} from "@iservice365/node-server-utils";
|
|
3132
3271
|
function useStockRepository() {
|
|
3133
3272
|
const db = useAtlas8.getDb();
|
|
@@ -3135,8 +3274,10 @@ function useStockRepository() {
|
|
|
3135
3274
|
throw new InternalServerError6("Unable to connect to server.");
|
|
3136
3275
|
}
|
|
3137
3276
|
const namespace_collection = "site.supply.stocks";
|
|
3277
|
+
const supply_collection = "site.supplies";
|
|
3138
3278
|
const collection = db.collection(namespace_collection);
|
|
3139
|
-
const { delNamespace } = useCache6(namespace_collection);
|
|
3279
|
+
const { delNamespace, setCache, getCache } = useCache6(namespace_collection);
|
|
3280
|
+
const { delNamespace: delSupplyNamespace } = useCache6(supply_collection);
|
|
3140
3281
|
async function createIndex() {
|
|
3141
3282
|
try {
|
|
3142
3283
|
await collection.createIndexes([
|
|
@@ -3154,49 +3295,135 @@ function useStockRepository() {
|
|
|
3154
3295
|
value = MStock(value);
|
|
3155
3296
|
const res = await collection.insertOne(value, { session });
|
|
3156
3297
|
delNamespace().then(() => {
|
|
3157
|
-
|
|
3298
|
+
logger20.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3158
3299
|
}).catch((err) => {
|
|
3159
|
-
|
|
3300
|
+
logger20.error(
|
|
3160
3301
|
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3161
3302
|
err
|
|
3162
3303
|
);
|
|
3163
3304
|
});
|
|
3305
|
+
delSupplyNamespace().then(() => {
|
|
3306
|
+
logger20.info(`Cache cleared for namespace: ${supply_collection}`);
|
|
3307
|
+
}).catch((err) => {
|
|
3308
|
+
logger20.error(
|
|
3309
|
+
`Failed to clear cache for namespace: ${supply_collection}`,
|
|
3310
|
+
err
|
|
3311
|
+
);
|
|
3312
|
+
});
|
|
3164
3313
|
return res.insertedId;
|
|
3165
3314
|
} catch (error) {
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3315
|
+
throw error;
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
async function getStocksBySupplyId({
|
|
3319
|
+
page = 1,
|
|
3320
|
+
limit = 10,
|
|
3321
|
+
search = "",
|
|
3322
|
+
site,
|
|
3323
|
+
supply
|
|
3324
|
+
}) {
|
|
3325
|
+
page = page > 0 ? page - 1 : 0;
|
|
3326
|
+
const query = {
|
|
3327
|
+
status: { $ne: "deleted" }
|
|
3328
|
+
};
|
|
3329
|
+
const cacheOptions = {
|
|
3330
|
+
page,
|
|
3331
|
+
limit
|
|
3332
|
+
};
|
|
3333
|
+
try {
|
|
3334
|
+
site = new ObjectId12(site);
|
|
3335
|
+
query.site = site;
|
|
3336
|
+
cacheOptions.site = site.toString();
|
|
3337
|
+
} catch (error) {
|
|
3338
|
+
throw new BadRequestError19("Invalid site ID format.");
|
|
3339
|
+
}
|
|
3340
|
+
try {
|
|
3341
|
+
supply = new ObjectId12(supply);
|
|
3342
|
+
query.supply = supply;
|
|
3343
|
+
cacheOptions.supply = supply.toString();
|
|
3344
|
+
} catch (error) {
|
|
3345
|
+
throw new BadRequestError19("Invalid supply ID format.");
|
|
3346
|
+
}
|
|
3347
|
+
if (search) {
|
|
3348
|
+
query.$text = { $search: search };
|
|
3349
|
+
cacheOptions.search = search;
|
|
3350
|
+
}
|
|
3351
|
+
const cacheKey = makeCacheKey6(namespace_collection, cacheOptions);
|
|
3352
|
+
const cachedData = await getCache(cacheKey);
|
|
3353
|
+
if (cachedData) {
|
|
3354
|
+
logger20.info(`Cache hit for key: ${cacheKey}`);
|
|
3355
|
+
return cachedData;
|
|
3356
|
+
}
|
|
3357
|
+
try {
|
|
3358
|
+
const items = await collection.aggregate([
|
|
3359
|
+
{ $match: query },
|
|
3360
|
+
{
|
|
3361
|
+
$project: {
|
|
3362
|
+
createdAt: 1,
|
|
3363
|
+
in: 1,
|
|
3364
|
+
out: 1,
|
|
3365
|
+
balance: 1
|
|
3366
|
+
}
|
|
3367
|
+
},
|
|
3368
|
+
{ $sort: { _id: 1 } },
|
|
3369
|
+
{ $skip: page * limit },
|
|
3370
|
+
{ $limit: limit }
|
|
3371
|
+
]).toArray();
|
|
3372
|
+
const length = await collection.countDocuments(query);
|
|
3373
|
+
const data = paginate6(items, page, limit, length);
|
|
3374
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
3375
|
+
logger20.info(`Cache set for key: ${cacheKey}`);
|
|
3376
|
+
}).catch((err) => {
|
|
3377
|
+
logger20.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3378
|
+
});
|
|
3379
|
+
return data;
|
|
3380
|
+
} catch (error) {
|
|
3170
3381
|
throw error;
|
|
3171
3382
|
}
|
|
3172
3383
|
}
|
|
3173
3384
|
return {
|
|
3174
3385
|
createIndex,
|
|
3175
|
-
createStock
|
|
3386
|
+
createStock,
|
|
3387
|
+
getStocksBySupplyId
|
|
3176
3388
|
};
|
|
3177
3389
|
}
|
|
3178
3390
|
|
|
3179
|
-
// src/services/hygiene-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3391
|
+
// src/services/hygiene-stock.service.ts
|
|
3392
|
+
import {
|
|
3393
|
+
NotFoundError as NotFoundError5,
|
|
3394
|
+
useAtlas as useAtlas9,
|
|
3395
|
+
BadRequestError as BadRequestError20
|
|
3396
|
+
} from "@iservice365/node-server-utils";
|
|
3397
|
+
function useStockService() {
|
|
3398
|
+
const { createStock: _createStock } = useStockRepository();
|
|
3399
|
+
const { getSupplyById, updateSupply } = useSupplyRepository();
|
|
3400
|
+
async function createStock(value, out = false) {
|
|
3184
3401
|
const session = useAtlas9.getClient()?.startSession();
|
|
3185
3402
|
try {
|
|
3186
3403
|
session?.startTransaction();
|
|
3187
|
-
const { qty,
|
|
3188
|
-
const supply = await
|
|
3189
|
-
|
|
3404
|
+
const { qty, ...stockData } = value;
|
|
3405
|
+
const supply = await getSupplyById(value.supply, session);
|
|
3406
|
+
if (!supply || supply.qty === void 0) {
|
|
3407
|
+
throw new NotFoundError5("Supply not found.");
|
|
3408
|
+
}
|
|
3409
|
+
const newSupplyQty = out ? supply.qty - qty : supply.qty + qty;
|
|
3410
|
+
if (out && newSupplyQty < 0) {
|
|
3411
|
+
throw new BadRequestError20(
|
|
3412
|
+
`Insufficient stock. Available: ${supply.qty}, Requested: ${qty}`
|
|
3413
|
+
);
|
|
3414
|
+
}
|
|
3415
|
+
await updateSupply(value.supply, { qty: newSupplyQty }, session);
|
|
3416
|
+
const createdStock = await _createStock(
|
|
3190
3417
|
{
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
balance:
|
|
3418
|
+
...stockData,
|
|
3419
|
+
in: out ? 0 : qty,
|
|
3420
|
+
out: out ? qty : 0,
|
|
3421
|
+
balance: newSupplyQty
|
|
3195
3422
|
},
|
|
3196
3423
|
session
|
|
3197
3424
|
);
|
|
3198
3425
|
await session?.commitTransaction();
|
|
3199
|
-
return
|
|
3426
|
+
return createdStock;
|
|
3200
3427
|
} catch (error) {
|
|
3201
3428
|
await session?.abortTransaction();
|
|
3202
3429
|
throw error;
|
|
@@ -3204,167 +3431,301 @@ function useSupplyService() {
|
|
|
3204
3431
|
await session?.endSession();
|
|
3205
3432
|
}
|
|
3206
3433
|
}
|
|
3207
|
-
return {
|
|
3434
|
+
return { createStock };
|
|
3208
3435
|
}
|
|
3209
3436
|
|
|
3210
|
-
// src/controllers/hygiene-
|
|
3211
|
-
import { BadRequestError as
|
|
3212
|
-
import
|
|
3213
|
-
function
|
|
3214
|
-
const {
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
updateSupply: _updateSupply,
|
|
3218
|
-
deleteSupply: _deleteSupply
|
|
3219
|
-
} = useSupplyRepository();
|
|
3220
|
-
const { createSupply: _createSupply } = useSupplyService();
|
|
3221
|
-
async function createSupply(req, res, next) {
|
|
3437
|
+
// src/controllers/hygiene-stock.controller.ts
|
|
3438
|
+
import { BadRequestError as BadRequestError21, logger as logger21 } from "@iservice365/node-server-utils";
|
|
3439
|
+
import Joi12 from "joi";
|
|
3440
|
+
function useStockController() {
|
|
3441
|
+
const { getStocksBySupplyId: _getStocksBySupplyId } = useStockRepository();
|
|
3442
|
+
const { createStock: _createStock } = useStockService();
|
|
3443
|
+
async function createStock(req, res, next) {
|
|
3222
3444
|
const payload = { ...req.body, ...req.params };
|
|
3223
|
-
const
|
|
3445
|
+
const validation = Joi12.object({
|
|
3446
|
+
site: Joi12.string().hex().required(),
|
|
3447
|
+
supply: Joi12.string().hex().required(),
|
|
3448
|
+
qty: Joi12.number().min(0).required(),
|
|
3449
|
+
remarks: Joi12.string().optional().allow("", null)
|
|
3450
|
+
});
|
|
3451
|
+
const { error } = validation.validate(payload);
|
|
3224
3452
|
if (error) {
|
|
3225
|
-
|
|
3226
|
-
next(new
|
|
3453
|
+
logger21.log({ level: "error", message: error.message });
|
|
3454
|
+
next(new BadRequestError21(error.message));
|
|
3227
3455
|
return;
|
|
3228
3456
|
}
|
|
3229
3457
|
try {
|
|
3230
|
-
const id = await
|
|
3231
|
-
res.status(201).json({ message: "
|
|
3458
|
+
const id = await _createStock(payload);
|
|
3459
|
+
res.status(201).json({ message: "Stock created successfully.", id });
|
|
3232
3460
|
return;
|
|
3233
3461
|
} catch (error2) {
|
|
3234
|
-
|
|
3462
|
+
logger21.log({ level: "error", message: error2.message });
|
|
3235
3463
|
next(error2);
|
|
3236
3464
|
return;
|
|
3237
3465
|
}
|
|
3238
3466
|
}
|
|
3239
|
-
async function
|
|
3467
|
+
async function getStocksBySupplyId(req, res, next) {
|
|
3240
3468
|
const query = { ...req.query, ...req.params };
|
|
3241
|
-
const validation =
|
|
3242
|
-
page:
|
|
3243
|
-
limit:
|
|
3244
|
-
search:
|
|
3245
|
-
site:
|
|
3469
|
+
const validation = Joi12.object({
|
|
3470
|
+
page: Joi12.number().min(1).optional().allow("", null),
|
|
3471
|
+
limit: Joi12.number().min(1).optional().allow("", null),
|
|
3472
|
+
search: Joi12.string().optional().allow("", null),
|
|
3473
|
+
site: Joi12.string().hex().required(),
|
|
3474
|
+
supply: Joi12.string().hex().required()
|
|
3246
3475
|
});
|
|
3247
3476
|
const { error } = validation.validate(query);
|
|
3248
3477
|
if (error) {
|
|
3249
|
-
|
|
3250
|
-
next(new
|
|
3478
|
+
logger21.log({ level: "error", message: error.message });
|
|
3479
|
+
next(new BadRequestError21(error.message));
|
|
3251
3480
|
return;
|
|
3252
3481
|
}
|
|
3253
3482
|
const page = parseInt(req.query.page) ?? 1;
|
|
3254
|
-
const limit = parseInt(req.query.limit) ??
|
|
3483
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
3255
3484
|
const search = req.query.search ?? "";
|
|
3256
3485
|
const site = req.params.site ?? "";
|
|
3486
|
+
const supply = req.params.supply ?? "";
|
|
3257
3487
|
try {
|
|
3258
|
-
const data = await
|
|
3488
|
+
const data = await _getStocksBySupplyId({
|
|
3259
3489
|
page,
|
|
3260
3490
|
limit,
|
|
3261
3491
|
search,
|
|
3262
|
-
site
|
|
3492
|
+
site,
|
|
3493
|
+
supply
|
|
3263
3494
|
});
|
|
3264
3495
|
res.json(data);
|
|
3265
3496
|
return;
|
|
3266
3497
|
} catch (error2) {
|
|
3267
|
-
|
|
3498
|
+
logger21.log({ level: "error", message: error2.message });
|
|
3268
3499
|
next(error2);
|
|
3269
3500
|
return;
|
|
3270
3501
|
}
|
|
3271
3502
|
}
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3503
|
+
return {
|
|
3504
|
+
createStock,
|
|
3505
|
+
getStocksBySupplyId
|
|
3506
|
+
};
|
|
3507
|
+
}
|
|
3508
|
+
|
|
3509
|
+
// src/models/hygiene-request-item.model.ts
|
|
3510
|
+
import { BadRequestError as BadRequestError22, logger as logger22 } from "@iservice365/node-server-utils";
|
|
3511
|
+
import Joi13 from "joi";
|
|
3512
|
+
import { ObjectId as ObjectId13 } from "mongodb";
|
|
3513
|
+
var allowedRequestItemStatus = [
|
|
3514
|
+
"pending",
|
|
3515
|
+
"approved",
|
|
3516
|
+
"disapproved"
|
|
3517
|
+
];
|
|
3518
|
+
var requestItemSchema = Joi13.object({
|
|
3519
|
+
site: Joi13.string().hex().required(),
|
|
3520
|
+
supply: Joi13.string().hex().required(),
|
|
3521
|
+
supplyName: Joi13.string().required(),
|
|
3522
|
+
qty: Joi13.number().min(0).required(),
|
|
3523
|
+
createdBy: Joi13.string().hex().required(),
|
|
3524
|
+
createdByName: Joi13.string().required()
|
|
3525
|
+
});
|
|
3526
|
+
function MRequestItem(value) {
|
|
3527
|
+
const { error } = requestItemSchema.validate(value);
|
|
3528
|
+
if (error) {
|
|
3529
|
+
logger22.info(`Hygiene Request Item Model: ${error.message}`);
|
|
3530
|
+
throw new BadRequestError22(error.message);
|
|
3531
|
+
}
|
|
3532
|
+
if (value.site) {
|
|
3533
|
+
try {
|
|
3534
|
+
value.site = new ObjectId13(value.site);
|
|
3535
|
+
} catch (error2) {
|
|
3536
|
+
throw new BadRequestError22("Invalid site ID format.");
|
|
3280
3537
|
}
|
|
3538
|
+
}
|
|
3539
|
+
if (value.supply) {
|
|
3281
3540
|
try {
|
|
3282
|
-
|
|
3283
|
-
res.json(data);
|
|
3284
|
-
return;
|
|
3541
|
+
value.supply = new ObjectId13(value.supply);
|
|
3285
3542
|
} catch (error2) {
|
|
3286
|
-
|
|
3287
|
-
next(error2);
|
|
3288
|
-
return;
|
|
3543
|
+
throw new BadRequestError22("Invalid supply ID format.");
|
|
3289
3544
|
}
|
|
3290
3545
|
}
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3546
|
+
return {
|
|
3547
|
+
site: value.site,
|
|
3548
|
+
supply: value.supply,
|
|
3549
|
+
supplyName: value.supplyName,
|
|
3550
|
+
qty: value.qty,
|
|
3551
|
+
remarks: "",
|
|
3552
|
+
createdBy: value.createdBy,
|
|
3553
|
+
createdByName: value.createdByName,
|
|
3554
|
+
status: "pending",
|
|
3555
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3556
|
+
updatedAt: "",
|
|
3557
|
+
deletedAt: ""
|
|
3558
|
+
};
|
|
3559
|
+
}
|
|
3560
|
+
|
|
3561
|
+
// src/repositories/hygiene-request-item.repository.ts
|
|
3562
|
+
import { ObjectId as ObjectId14 } from "mongodb";
|
|
3563
|
+
import {
|
|
3564
|
+
useAtlas as useAtlas10,
|
|
3565
|
+
InternalServerError as InternalServerError7,
|
|
3566
|
+
useCache as useCache7,
|
|
3567
|
+
logger as logger23,
|
|
3568
|
+
makeCacheKey as makeCacheKey7,
|
|
3569
|
+
paginate as paginate7,
|
|
3570
|
+
BadRequestError as BadRequestError23
|
|
3571
|
+
} from "@iservice365/node-server-utils";
|
|
3572
|
+
function useRequestItemRepository() {
|
|
3573
|
+
const db = useAtlas10.getDb();
|
|
3574
|
+
if (!db) {
|
|
3575
|
+
throw new InternalServerError7("Unable to connect to server.");
|
|
3576
|
+
}
|
|
3577
|
+
const namespace_collection = "site.supply.requests";
|
|
3578
|
+
const collection = db.collection(namespace_collection);
|
|
3579
|
+
const { delNamespace, setCache, getCache } = useCache7(namespace_collection);
|
|
3580
|
+
async function createIndex() {
|
|
3581
|
+
try {
|
|
3582
|
+
await collection.createIndexes([
|
|
3583
|
+
{ key: { site: 1 } },
|
|
3584
|
+
{ key: { supply: 1 } },
|
|
3585
|
+
{ key: { status: 1 } }
|
|
3586
|
+
]);
|
|
3587
|
+
} catch (error) {
|
|
3588
|
+
throw new InternalServerError7(
|
|
3589
|
+
"Failed to create index on hygiene request item."
|
|
3590
|
+
);
|
|
3304
3591
|
}
|
|
3592
|
+
}
|
|
3593
|
+
async function createTextIndex() {
|
|
3305
3594
|
try {
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
logger20.log({ level: "error", message: error2.message });
|
|
3312
|
-
next(error2);
|
|
3313
|
-
return;
|
|
3595
|
+
await collection.createIndex({ supplyName: "text" });
|
|
3596
|
+
} catch (error) {
|
|
3597
|
+
throw new InternalServerError7(
|
|
3598
|
+
"Failed to create text index on hygiene supply."
|
|
3599
|
+
);
|
|
3314
3600
|
}
|
|
3315
3601
|
}
|
|
3316
|
-
async function
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3602
|
+
async function createRequestItem(value, session) {
|
|
3603
|
+
try {
|
|
3604
|
+
value = MRequestItem(value);
|
|
3605
|
+
const res = await collection.insertOne(value, { session });
|
|
3606
|
+
delNamespace().then(() => {
|
|
3607
|
+
logger23.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3608
|
+
}).catch((err) => {
|
|
3609
|
+
logger23.error(
|
|
3610
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3611
|
+
err
|
|
3612
|
+
);
|
|
3613
|
+
});
|
|
3614
|
+
return res.insertedId;
|
|
3615
|
+
} catch (error) {
|
|
3616
|
+
throw error;
|
|
3326
3617
|
}
|
|
3618
|
+
}
|
|
3619
|
+
async function getRequestItems({
|
|
3620
|
+
page = 1,
|
|
3621
|
+
limit = 10,
|
|
3622
|
+
search = "",
|
|
3623
|
+
site
|
|
3624
|
+
}) {
|
|
3625
|
+
page = page > 0 ? page - 1 : 0;
|
|
3626
|
+
const query = {
|
|
3627
|
+
status: { $ne: "deleted" }
|
|
3628
|
+
};
|
|
3629
|
+
const cacheOptions = {
|
|
3630
|
+
page,
|
|
3631
|
+
limit
|
|
3632
|
+
};
|
|
3327
3633
|
try {
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
} catch (
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3634
|
+
site = new ObjectId14(site);
|
|
3635
|
+
query.site = site;
|
|
3636
|
+
cacheOptions.site = site.toString();
|
|
3637
|
+
} catch (error) {
|
|
3638
|
+
throw new BadRequestError23("Invalid site ID format.");
|
|
3639
|
+
}
|
|
3640
|
+
if (search) {
|
|
3641
|
+
query.$text = { $search: search };
|
|
3642
|
+
cacheOptions.search = search;
|
|
3643
|
+
}
|
|
3644
|
+
const cacheKey = makeCacheKey7(namespace_collection, cacheOptions);
|
|
3645
|
+
const cachedData = await getCache(cacheKey);
|
|
3646
|
+
if (cachedData) {
|
|
3647
|
+
logger23.info(`Cache hit for key: ${cacheKey}`);
|
|
3648
|
+
return cachedData;
|
|
3649
|
+
}
|
|
3650
|
+
try {
|
|
3651
|
+
const items = await collection.aggregate([
|
|
3652
|
+
{ $match: query },
|
|
3653
|
+
{
|
|
3654
|
+
$project: {
|
|
3655
|
+
createdAt: 1,
|
|
3656
|
+
status: 1
|
|
3657
|
+
}
|
|
3658
|
+
},
|
|
3659
|
+
{ $sort: { _id: 1 } },
|
|
3660
|
+
{ $skip: page * limit },
|
|
3661
|
+
{ $limit: limit }
|
|
3662
|
+
]).toArray();
|
|
3663
|
+
const length = await collection.countDocuments(query);
|
|
3664
|
+
const data = paginate7(items, page, limit, length);
|
|
3665
|
+
setCache(cacheKey, data, 15 * 60).then(() => {
|
|
3666
|
+
logger23.info(`Cache set for key: ${cacheKey}`);
|
|
3667
|
+
}).catch((err) => {
|
|
3668
|
+
logger23.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
3669
|
+
});
|
|
3670
|
+
return data;
|
|
3671
|
+
} catch (error) {
|
|
3672
|
+
throw error;
|
|
3335
3673
|
}
|
|
3336
3674
|
}
|
|
3337
3675
|
return {
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
deleteSupply
|
|
3676
|
+
createIndex,
|
|
3677
|
+
createTextIndex,
|
|
3678
|
+
createRequestItem,
|
|
3679
|
+
getRequestItems
|
|
3343
3680
|
};
|
|
3344
3681
|
}
|
|
3345
3682
|
|
|
3346
|
-
// src/services/hygiene-
|
|
3347
|
-
import {
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
const {
|
|
3351
|
-
|
|
3352
|
-
|
|
3683
|
+
// src/services/hygiene-request-item.service.ts
|
|
3684
|
+
import { useAtlas as useAtlas11 } from "@iservice365/node-server-utils";
|
|
3685
|
+
import { useUserRepo } from "@iservice365/core";
|
|
3686
|
+
function useRequestItemService() {
|
|
3687
|
+
const { createRequestItem: _createRequestItem } = useRequestItemRepository();
|
|
3688
|
+
const { getSupplyById } = useSupplyRepository();
|
|
3689
|
+
const { getUserById } = useUserRepo();
|
|
3690
|
+
async function createRequestItem(value) {
|
|
3691
|
+
try {
|
|
3692
|
+
const { supply, createdBy } = value;
|
|
3693
|
+
const supplyData = await getSupplyById(supply);
|
|
3694
|
+
const createdByData = await getUserById(createdBy);
|
|
3695
|
+
const createdRequestItem = await _createRequestItem({
|
|
3696
|
+
...value,
|
|
3697
|
+
supplyName: supplyData?.name || "",
|
|
3698
|
+
createdByName: createdByData?.name || ""
|
|
3699
|
+
});
|
|
3700
|
+
return createdRequestItem;
|
|
3701
|
+
} catch (error) {
|
|
3702
|
+
throw error;
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3705
|
+
async function createRequestItemByBatch(value) {
|
|
3706
|
+
const session = useAtlas11.getClient()?.startSession();
|
|
3353
3707
|
try {
|
|
3354
3708
|
session?.startTransaction();
|
|
3355
|
-
const {
|
|
3356
|
-
const
|
|
3357
|
-
|
|
3358
|
-
|
|
3709
|
+
const { site, createdBy, items } = value;
|
|
3710
|
+
const createdByData = await getUserById(createdBy);
|
|
3711
|
+
const createdRequestItemIds = [];
|
|
3712
|
+
for (const item of items) {
|
|
3713
|
+
const supplyData = await getSupplyById(item.supply, session);
|
|
3714
|
+
const createdId = await _createRequestItem(
|
|
3715
|
+
{
|
|
3716
|
+
site,
|
|
3717
|
+
supply: item.supply,
|
|
3718
|
+
qty: item.qty,
|
|
3719
|
+
supplyName: supplyData?.name || "",
|
|
3720
|
+
createdBy,
|
|
3721
|
+
createdByName: createdByData?.name || ""
|
|
3722
|
+
},
|
|
3723
|
+
session
|
|
3724
|
+
);
|
|
3725
|
+
createdRequestItemIds.push(createdId);
|
|
3359
3726
|
}
|
|
3360
|
-
const newSupplyQty = supply.qty + qty;
|
|
3361
|
-
await updateSupply(value.supply, { qty: newSupplyQty }, session);
|
|
3362
|
-
const createdStock = await _createStock(
|
|
3363
|
-
{ ...stockData, in: qty, balance: newSupplyQty },
|
|
3364
|
-
session
|
|
3365
|
-
);
|
|
3366
3727
|
await session?.commitTransaction();
|
|
3367
|
-
return
|
|
3728
|
+
return createdRequestItemIds;
|
|
3368
3729
|
} catch (error) {
|
|
3369
3730
|
await session?.abortTransaction();
|
|
3370
3731
|
throw error;
|
|
@@ -3372,55 +3733,143 @@ function useStockService() {
|
|
|
3372
3733
|
await session?.endSession();
|
|
3373
3734
|
}
|
|
3374
3735
|
}
|
|
3375
|
-
return {
|
|
3736
|
+
return { createRequestItem, createRequestItemByBatch };
|
|
3376
3737
|
}
|
|
3377
3738
|
|
|
3378
|
-
// src/controllers/hygiene-
|
|
3379
|
-
import { BadRequestError as
|
|
3380
|
-
import
|
|
3381
|
-
function
|
|
3382
|
-
const {
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3739
|
+
// src/controllers/hygiene-request-item.controller.ts
|
|
3740
|
+
import { BadRequestError as BadRequestError24, logger as logger24 } from "@iservice365/node-server-utils";
|
|
3741
|
+
import Joi14 from "joi";
|
|
3742
|
+
function useRequestItemController() {
|
|
3743
|
+
const { getRequestItems: _getRequestItems } = useRequestItemRepository();
|
|
3744
|
+
const {
|
|
3745
|
+
createRequestItem: _createRequestItem,
|
|
3746
|
+
createRequestItemByBatch: _createRequestItemByBatch
|
|
3747
|
+
} = useRequestItemService();
|
|
3748
|
+
async function createRequestItem(req, res, next) {
|
|
3749
|
+
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
3750
|
+
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
3751
|
+
{}
|
|
3752
|
+
) : {};
|
|
3753
|
+
const createdBy = cookies["user"] || "";
|
|
3754
|
+
const payload = {
|
|
3755
|
+
...req.body,
|
|
3756
|
+
...req.params,
|
|
3757
|
+
createdBy
|
|
3758
|
+
};
|
|
3759
|
+
const validation = Joi14.object({
|
|
3760
|
+
site: Joi14.string().hex().required(),
|
|
3761
|
+
supply: Joi14.string().hex().required(),
|
|
3762
|
+
qty: Joi14.number().min(0).required(),
|
|
3763
|
+
createdBy: Joi14.string().hex().required()
|
|
3390
3764
|
});
|
|
3391
3765
|
const { error } = validation.validate(payload);
|
|
3392
3766
|
if (error) {
|
|
3393
|
-
|
|
3394
|
-
next(new
|
|
3767
|
+
logger24.log({ level: "error", message: error.message });
|
|
3768
|
+
next(new BadRequestError24(error.message));
|
|
3395
3769
|
return;
|
|
3396
3770
|
}
|
|
3397
3771
|
try {
|
|
3398
|
-
const id = await
|
|
3399
|
-
res.status(201).json({ message: "
|
|
3772
|
+
const id = await _createRequestItem(payload);
|
|
3773
|
+
res.status(201).json({ message: "Request item created successfully.", id });
|
|
3400
3774
|
return;
|
|
3401
3775
|
} catch (error2) {
|
|
3402
|
-
|
|
3776
|
+
logger24.log({ level: "error", message: error2.message });
|
|
3777
|
+
next(error2);
|
|
3778
|
+
return;
|
|
3779
|
+
}
|
|
3780
|
+
}
|
|
3781
|
+
async function createRequestItemByBatch(req, res, next) {
|
|
3782
|
+
const cookies = req.headers.cookie ? req.headers.cookie.split(";").map((cookie) => cookie.trim().split("=")).reduce(
|
|
3783
|
+
(acc, [key, value]) => ({ ...acc, [key]: value }),
|
|
3784
|
+
{}
|
|
3785
|
+
) : {};
|
|
3786
|
+
const createdBy = cookies["user"] || "";
|
|
3787
|
+
const payload = {
|
|
3788
|
+
...req.body,
|
|
3789
|
+
...req.params,
|
|
3790
|
+
createdBy
|
|
3791
|
+
};
|
|
3792
|
+
const validation = Joi14.object({
|
|
3793
|
+
site: Joi14.string().hex().required(),
|
|
3794
|
+
createdBy: Joi14.string().hex().required(),
|
|
3795
|
+
items: Joi14.array().items(
|
|
3796
|
+
Joi14.object({
|
|
3797
|
+
supply: Joi14.string().hex().required(),
|
|
3798
|
+
qty: Joi14.number().min(0).required()
|
|
3799
|
+
})
|
|
3800
|
+
).min(1).required()
|
|
3801
|
+
});
|
|
3802
|
+
const { error } = validation.validate(payload);
|
|
3803
|
+
if (error) {
|
|
3804
|
+
logger24.log({ level: "error", message: error.message });
|
|
3805
|
+
next(new BadRequestError24(error.message));
|
|
3806
|
+
return;
|
|
3807
|
+
}
|
|
3808
|
+
try {
|
|
3809
|
+
await _createRequestItemByBatch(payload);
|
|
3810
|
+
res.status(201).json({ message: "Request items created successfully." });
|
|
3811
|
+
return;
|
|
3812
|
+
} catch (error2) {
|
|
3813
|
+
logger24.log({ level: "error", message: error2.message });
|
|
3814
|
+
next(error2);
|
|
3815
|
+
return;
|
|
3816
|
+
}
|
|
3817
|
+
}
|
|
3818
|
+
async function getRequestItems(req, res, next) {
|
|
3819
|
+
const query = { ...req.query, ...req.params };
|
|
3820
|
+
const validation = Joi14.object({
|
|
3821
|
+
page: Joi14.number().min(1).optional().allow("", null),
|
|
3822
|
+
limit: Joi14.number().min(1).optional().allow("", null),
|
|
3823
|
+
search: Joi14.string().optional().allow("", null),
|
|
3824
|
+
site: Joi14.string().hex().required()
|
|
3825
|
+
});
|
|
3826
|
+
const { error } = validation.validate(query);
|
|
3827
|
+
if (error) {
|
|
3828
|
+
logger24.log({ level: "error", message: error.message });
|
|
3829
|
+
next(new BadRequestError24(error.message));
|
|
3830
|
+
return;
|
|
3831
|
+
}
|
|
3832
|
+
const page = parseInt(req.query.page) ?? 1;
|
|
3833
|
+
const limit = parseInt(req.query.limit) ?? 10;
|
|
3834
|
+
const search = req.query.search ?? "";
|
|
3835
|
+
const site = req.params.site ?? "";
|
|
3836
|
+
try {
|
|
3837
|
+
const data = await _getRequestItems({
|
|
3838
|
+
page,
|
|
3839
|
+
limit,
|
|
3840
|
+
search,
|
|
3841
|
+
site
|
|
3842
|
+
});
|
|
3843
|
+
res.json(data);
|
|
3844
|
+
return;
|
|
3845
|
+
} catch (error2) {
|
|
3846
|
+
logger24.log({ level: "error", message: error2.message });
|
|
3403
3847
|
next(error2);
|
|
3404
3848
|
return;
|
|
3405
3849
|
}
|
|
3406
3850
|
}
|
|
3407
3851
|
return {
|
|
3408
|
-
|
|
3852
|
+
createRequestItem,
|
|
3853
|
+
createRequestItemByBatch,
|
|
3854
|
+
getRequestItems
|
|
3409
3855
|
};
|
|
3410
3856
|
}
|
|
3411
3857
|
export {
|
|
3412
3858
|
MArea,
|
|
3413
3859
|
MAreaChecklist,
|
|
3414
3860
|
MParentChecklist,
|
|
3861
|
+
MRequestItem,
|
|
3415
3862
|
MStock,
|
|
3416
3863
|
MSupply,
|
|
3417
3864
|
MUnit,
|
|
3418
3865
|
allowedChecklistStatus,
|
|
3866
|
+
allowedRequestItemStatus,
|
|
3419
3867
|
allowedStatus,
|
|
3420
3868
|
allowedTypes,
|
|
3421
3869
|
areaChecklistSchema,
|
|
3422
3870
|
areaSchema,
|
|
3423
3871
|
parentChecklistSchema,
|
|
3872
|
+
requestItemSchema,
|
|
3424
3873
|
stockSchema,
|
|
3425
3874
|
supplySchema,
|
|
3426
3875
|
unitSchema,
|
|
@@ -3432,12 +3881,14 @@ export {
|
|
|
3432
3881
|
useAreaService,
|
|
3433
3882
|
useParentChecklistController,
|
|
3434
3883
|
useParentChecklistRepo,
|
|
3884
|
+
useRequestItemController,
|
|
3885
|
+
useRequestItemRepository,
|
|
3886
|
+
useRequestItemService,
|
|
3435
3887
|
useStockController,
|
|
3436
3888
|
useStockRepository,
|
|
3437
3889
|
useStockService,
|
|
3438
3890
|
useSupplyController,
|
|
3439
3891
|
useSupplyRepository,
|
|
3440
|
-
useSupplyService,
|
|
3441
3892
|
useUnitController,
|
|
3442
3893
|
useUnitRepository,
|
|
3443
3894
|
useUnitService
|