@iservice365/module-hygiene 1.0.1 → 1.0.3
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 +13 -0
- package/dist/index.d.ts +54 -3
- package/dist/index.js +298 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +300 -28
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -2818,8 +2818,8 @@ function MSupply(value) {
|
|
|
2818
2818
|
name: value.name,
|
|
2819
2819
|
unitOfMeasurement: value.unitOfMeasurement,
|
|
2820
2820
|
qty: value.qty,
|
|
2821
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
2822
2821
|
status: "active",
|
|
2822
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2823
2823
|
updatedAt: "",
|
|
2824
2824
|
deletedAt: ""
|
|
2825
2825
|
};
|
|
@@ -2834,7 +2834,8 @@ import {
|
|
|
2834
2834
|
BadRequestError as BadRequestError16,
|
|
2835
2835
|
useCache as useCache5,
|
|
2836
2836
|
logger as logger17,
|
|
2837
|
-
makeCacheKey as makeCacheKey5
|
|
2837
|
+
makeCacheKey as makeCacheKey5,
|
|
2838
|
+
NotFoundError as NotFoundError4
|
|
2838
2839
|
} from "@iservice365/node-server-utils";
|
|
2839
2840
|
function useSupplyRepository() {
|
|
2840
2841
|
const db = useAtlas7.getDb();
|
|
@@ -2951,6 +2952,48 @@ function useSupplyRepository() {
|
|
|
2951
2952
|
throw error;
|
|
2952
2953
|
}
|
|
2953
2954
|
}
|
|
2955
|
+
async function getSupplyById(_id) {
|
|
2956
|
+
try {
|
|
2957
|
+
_id = new ObjectId10(_id);
|
|
2958
|
+
} catch (error) {
|
|
2959
|
+
throw new BadRequestError16("Invalid supply ID format.");
|
|
2960
|
+
}
|
|
2961
|
+
const query = {
|
|
2962
|
+
_id,
|
|
2963
|
+
status: { $ne: "deleted" }
|
|
2964
|
+
};
|
|
2965
|
+
const cacheKey = makeCacheKey5(namespace_collection, {
|
|
2966
|
+
_id: _id.toString()
|
|
2967
|
+
});
|
|
2968
|
+
const cachedData = await getCache(cacheKey);
|
|
2969
|
+
if (cachedData) {
|
|
2970
|
+
logger17.info(`Cache hit for key: ${cacheKey}`);
|
|
2971
|
+
return cachedData;
|
|
2972
|
+
}
|
|
2973
|
+
try {
|
|
2974
|
+
const data = await collection.aggregate([
|
|
2975
|
+
{ $match: query },
|
|
2976
|
+
{
|
|
2977
|
+
$project: {
|
|
2978
|
+
name: 1,
|
|
2979
|
+
unitOfMeasurement: 1,
|
|
2980
|
+
qty: 1
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
]).toArray();
|
|
2984
|
+
if (!data || data.length === 0) {
|
|
2985
|
+
throw new NotFoundError4("Supply not found.");
|
|
2986
|
+
}
|
|
2987
|
+
setCache(cacheKey, data[0], 15 * 60).then(() => {
|
|
2988
|
+
logger17.info(`Cache set for key: ${cacheKey}`);
|
|
2989
|
+
}).catch((err) => {
|
|
2990
|
+
logger17.error(`Failed to set cache for key: ${cacheKey}`, err);
|
|
2991
|
+
});
|
|
2992
|
+
return data[0];
|
|
2993
|
+
} catch (error) {
|
|
2994
|
+
throw error;
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2954
2997
|
async function updateSupply(_id, value, session) {
|
|
2955
2998
|
try {
|
|
2956
2999
|
_id = new ObjectId10(_id);
|
|
@@ -3023,27 +3066,164 @@ function useSupplyRepository() {
|
|
|
3023
3066
|
createUniqueIndex,
|
|
3024
3067
|
createSupply,
|
|
3025
3068
|
getSupplies,
|
|
3069
|
+
getSupplyById,
|
|
3026
3070
|
updateSupply,
|
|
3027
3071
|
deleteSupply
|
|
3028
3072
|
};
|
|
3029
3073
|
}
|
|
3030
3074
|
|
|
3031
|
-
// src/
|
|
3075
|
+
// src/services/hygiene-supply.service.ts
|
|
3076
|
+
import { useAtlas as useAtlas9 } from "@iservice365/node-server-utils";
|
|
3077
|
+
|
|
3078
|
+
// src/models/hygiene-stock.model.ts
|
|
3032
3079
|
import { BadRequestError as BadRequestError17, logger as logger18 } from "@iservice365/node-server-utils";
|
|
3033
3080
|
import Joi10 from "joi";
|
|
3081
|
+
import { ObjectId as ObjectId11 } from "mongodb";
|
|
3082
|
+
var stockSchema = Joi10.object({
|
|
3083
|
+
site: Joi10.string().hex().required(),
|
|
3084
|
+
supply: Joi10.string().hex().required(),
|
|
3085
|
+
in: Joi10.number().min(0).optional(),
|
|
3086
|
+
out: Joi10.number().min(0).optional(),
|
|
3087
|
+
balance: Joi10.number().min(0).required(),
|
|
3088
|
+
remarks: Joi10.string().optional().allow("", null)
|
|
3089
|
+
});
|
|
3090
|
+
function MStock(value) {
|
|
3091
|
+
const { error } = stockSchema.validate(value);
|
|
3092
|
+
if (error) {
|
|
3093
|
+
logger18.info(`Hygiene Stock Model: ${error.message}`);
|
|
3094
|
+
throw new BadRequestError17(error.message);
|
|
3095
|
+
}
|
|
3096
|
+
if (value.site) {
|
|
3097
|
+
try {
|
|
3098
|
+
value.site = new ObjectId11(value.site);
|
|
3099
|
+
} catch (error2) {
|
|
3100
|
+
throw new BadRequestError17("Invalid site ID format.");
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
if (value.supply) {
|
|
3104
|
+
try {
|
|
3105
|
+
value.supply = new ObjectId11(value.supply);
|
|
3106
|
+
} catch (error2) {
|
|
3107
|
+
throw new BadRequestError17("Invalid supply ID format.");
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
return {
|
|
3111
|
+
site: value.site,
|
|
3112
|
+
supply: value.supply,
|
|
3113
|
+
in: value.in ?? 0,
|
|
3114
|
+
out: value.out ?? 0,
|
|
3115
|
+
balance: value.balance,
|
|
3116
|
+
remarks: value.remarks ?? "",
|
|
3117
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3118
|
+
status: "active",
|
|
3119
|
+
updatedAt: "",
|
|
3120
|
+
deletedAt: ""
|
|
3121
|
+
};
|
|
3122
|
+
}
|
|
3123
|
+
|
|
3124
|
+
// src/repositories/hygiene-stock.repository.ts
|
|
3125
|
+
import {
|
|
3126
|
+
useAtlas as useAtlas8,
|
|
3127
|
+
InternalServerError as InternalServerError6,
|
|
3128
|
+
BadRequestError as BadRequestError18,
|
|
3129
|
+
useCache as useCache6,
|
|
3130
|
+
logger as logger19
|
|
3131
|
+
} from "@iservice365/node-server-utils";
|
|
3132
|
+
function useStockRepository() {
|
|
3133
|
+
const db = useAtlas8.getDb();
|
|
3134
|
+
if (!db) {
|
|
3135
|
+
throw new InternalServerError6("Unable to connect to server.");
|
|
3136
|
+
}
|
|
3137
|
+
const namespace_collection = "site.supply.stocks";
|
|
3138
|
+
const collection = db.collection(namespace_collection);
|
|
3139
|
+
const { delNamespace } = useCache6(namespace_collection);
|
|
3140
|
+
async function createIndex() {
|
|
3141
|
+
try {
|
|
3142
|
+
await collection.createIndexes([
|
|
3143
|
+
{ key: { site: 1 } },
|
|
3144
|
+
{ key: { supply: 1 } },
|
|
3145
|
+
{ key: { balance: 1 } },
|
|
3146
|
+
{ key: { status: 1 } }
|
|
3147
|
+
]);
|
|
3148
|
+
} catch (error) {
|
|
3149
|
+
throw new InternalServerError6("Failed to create index on hygiene stock.");
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
async function createStock(value, session) {
|
|
3153
|
+
try {
|
|
3154
|
+
value = MStock(value);
|
|
3155
|
+
const res = await collection.insertOne(value, { session });
|
|
3156
|
+
delNamespace().then(() => {
|
|
3157
|
+
logger19.info(`Cache cleared for namespace: ${namespace_collection}`);
|
|
3158
|
+
}).catch((err) => {
|
|
3159
|
+
logger19.error(
|
|
3160
|
+
`Failed to clear cache for namespace: ${namespace_collection}`,
|
|
3161
|
+
err
|
|
3162
|
+
);
|
|
3163
|
+
});
|
|
3164
|
+
return res.insertedId;
|
|
3165
|
+
} catch (error) {
|
|
3166
|
+
const isDuplicated = error.message.includes("duplicate");
|
|
3167
|
+
if (isDuplicated) {
|
|
3168
|
+
throw new BadRequestError18("Stock already exists.");
|
|
3169
|
+
}
|
|
3170
|
+
throw error;
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3173
|
+
return {
|
|
3174
|
+
createIndex,
|
|
3175
|
+
createStock
|
|
3176
|
+
};
|
|
3177
|
+
}
|
|
3178
|
+
|
|
3179
|
+
// src/services/hygiene-supply.service.ts
|
|
3180
|
+
function useSupplyService() {
|
|
3181
|
+
const { createSupply: _createSupply } = useSupplyRepository();
|
|
3182
|
+
const { createStock } = useStockRepository();
|
|
3183
|
+
async function createSupply(value) {
|
|
3184
|
+
const session = useAtlas9.getClient()?.startSession();
|
|
3185
|
+
try {
|
|
3186
|
+
session?.startTransaction();
|
|
3187
|
+
const { qty, site } = value;
|
|
3188
|
+
const supply = await _createSupply(value, session);
|
|
3189
|
+
const createdSupply = await createStock(
|
|
3190
|
+
{
|
|
3191
|
+
site,
|
|
3192
|
+
supply: supply.toString(),
|
|
3193
|
+
in: qty,
|
|
3194
|
+
balance: qty
|
|
3195
|
+
},
|
|
3196
|
+
session
|
|
3197
|
+
);
|
|
3198
|
+
await session?.commitTransaction();
|
|
3199
|
+
return createdSupply;
|
|
3200
|
+
} catch (error) {
|
|
3201
|
+
await session?.abortTransaction();
|
|
3202
|
+
throw error;
|
|
3203
|
+
} finally {
|
|
3204
|
+
await session?.endSession();
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
return { createSupply };
|
|
3208
|
+
}
|
|
3209
|
+
|
|
3210
|
+
// src/controllers/hygiene-supply.controller.ts
|
|
3211
|
+
import { BadRequestError as BadRequestError19, logger as logger20 } from "@iservice365/node-server-utils";
|
|
3212
|
+
import Joi11 from "joi";
|
|
3034
3213
|
function useSupplyController() {
|
|
3035
3214
|
const {
|
|
3036
|
-
createSupply: _createSupply,
|
|
3037
3215
|
getSupplies: _getSupplies,
|
|
3216
|
+
getSupplyById: _getSupplyById,
|
|
3038
3217
|
updateSupply: _updateSupply,
|
|
3039
3218
|
deleteSupply: _deleteSupply
|
|
3040
3219
|
} = useSupplyRepository();
|
|
3220
|
+
const { createSupply: _createSupply } = useSupplyService();
|
|
3041
3221
|
async function createSupply(req, res, next) {
|
|
3042
3222
|
const payload = { ...req.body, ...req.params };
|
|
3043
3223
|
const { error } = supplySchema.validate(payload);
|
|
3044
3224
|
if (error) {
|
|
3045
|
-
|
|
3046
|
-
next(new
|
|
3225
|
+
logger20.log({ level: "error", message: error.message });
|
|
3226
|
+
next(new BadRequestError19(error.message));
|
|
3047
3227
|
return;
|
|
3048
3228
|
}
|
|
3049
3229
|
try {
|
|
@@ -3051,23 +3231,23 @@ function useSupplyController() {
|
|
|
3051
3231
|
res.status(201).json({ message: "Supply created successfully.", id });
|
|
3052
3232
|
return;
|
|
3053
3233
|
} catch (error2) {
|
|
3054
|
-
|
|
3234
|
+
logger20.log({ level: "error", message: error2.message });
|
|
3055
3235
|
next(error2);
|
|
3056
3236
|
return;
|
|
3057
3237
|
}
|
|
3058
3238
|
}
|
|
3059
3239
|
async function getSupplies(req, res, next) {
|
|
3060
3240
|
const query = { ...req.query, ...req.params };
|
|
3061
|
-
const validation =
|
|
3062
|
-
page:
|
|
3063
|
-
limit:
|
|
3064
|
-
search:
|
|
3065
|
-
site:
|
|
3241
|
+
const validation = Joi11.object({
|
|
3242
|
+
page: Joi11.number().min(1).optional().allow("", null),
|
|
3243
|
+
limit: Joi11.number().min(1).optional().allow("", null),
|
|
3244
|
+
search: Joi11.string().optional().allow("", null),
|
|
3245
|
+
site: Joi11.string().hex().required()
|
|
3066
3246
|
});
|
|
3067
3247
|
const { error } = validation.validate(query);
|
|
3068
3248
|
if (error) {
|
|
3069
|
-
|
|
3070
|
-
next(new
|
|
3249
|
+
logger20.log({ level: "error", message: error.message });
|
|
3250
|
+
next(new BadRequestError19(error.message));
|
|
3071
3251
|
return;
|
|
3072
3252
|
}
|
|
3073
3253
|
const page = parseInt(req.query.page) ?? 1;
|
|
@@ -3084,23 +3264,42 @@ function useSupplyController() {
|
|
|
3084
3264
|
res.json(data);
|
|
3085
3265
|
return;
|
|
3086
3266
|
} catch (error2) {
|
|
3087
|
-
|
|
3267
|
+
logger20.log({ level: "error", message: error2.message });
|
|
3268
|
+
next(error2);
|
|
3269
|
+
return;
|
|
3270
|
+
}
|
|
3271
|
+
}
|
|
3272
|
+
async function getSupplyById(req, res, next) {
|
|
3273
|
+
const validation = Joi11.string().hex().required();
|
|
3274
|
+
const _id = req.params.id;
|
|
3275
|
+
const { error } = validation.validate(_id);
|
|
3276
|
+
if (error) {
|
|
3277
|
+
logger20.log({ level: "error", message: error.message });
|
|
3278
|
+
next(new BadRequestError19(error.message));
|
|
3279
|
+
return;
|
|
3280
|
+
}
|
|
3281
|
+
try {
|
|
3282
|
+
const data = await _getSupplyById(_id);
|
|
3283
|
+
res.json(data);
|
|
3284
|
+
return;
|
|
3285
|
+
} catch (error2) {
|
|
3286
|
+
logger20.log({ level: "error", message: error2.message });
|
|
3088
3287
|
next(error2);
|
|
3089
3288
|
return;
|
|
3090
3289
|
}
|
|
3091
3290
|
}
|
|
3092
3291
|
async function updateSupply(req, res, next) {
|
|
3093
3292
|
const payload = { id: req.params.id, ...req.body };
|
|
3094
|
-
const validation =
|
|
3095
|
-
id:
|
|
3096
|
-
name:
|
|
3097
|
-
unitOfMeasurement:
|
|
3098
|
-
qty:
|
|
3293
|
+
const validation = Joi11.object({
|
|
3294
|
+
id: Joi11.string().hex().required(),
|
|
3295
|
+
name: Joi11.string().optional().allow("", null),
|
|
3296
|
+
unitOfMeasurement: Joi11.string().optional().allow("", null),
|
|
3297
|
+
qty: Joi11.number().min(0).optional().allow("", null)
|
|
3099
3298
|
});
|
|
3100
3299
|
const { error } = validation.validate(payload);
|
|
3101
3300
|
if (error) {
|
|
3102
|
-
|
|
3103
|
-
next(new
|
|
3301
|
+
logger20.log({ level: "error", message: error.message });
|
|
3302
|
+
next(new BadRequestError19(error.message));
|
|
3104
3303
|
return;
|
|
3105
3304
|
}
|
|
3106
3305
|
try {
|
|
@@ -3109,20 +3308,20 @@ function useSupplyController() {
|
|
|
3109
3308
|
res.json({ message: "Supply updated successfully." });
|
|
3110
3309
|
return;
|
|
3111
3310
|
} catch (error2) {
|
|
3112
|
-
|
|
3311
|
+
logger20.log({ level: "error", message: error2.message });
|
|
3113
3312
|
next(error2);
|
|
3114
3313
|
return;
|
|
3115
3314
|
}
|
|
3116
3315
|
}
|
|
3117
3316
|
async function deleteSupply(req, res, next) {
|
|
3118
3317
|
const id = req.params.id;
|
|
3119
|
-
const validation =
|
|
3120
|
-
id:
|
|
3318
|
+
const validation = Joi11.object({
|
|
3319
|
+
id: Joi11.string().hex().required()
|
|
3121
3320
|
});
|
|
3122
3321
|
const { error } = validation.validate({ id });
|
|
3123
3322
|
if (error) {
|
|
3124
|
-
|
|
3125
|
-
next(new
|
|
3323
|
+
logger20.log({ level: "error", message: error.message });
|
|
3324
|
+
next(new BadRequestError19(error.message));
|
|
3126
3325
|
return;
|
|
3127
3326
|
}
|
|
3128
3327
|
try {
|
|
@@ -3130,7 +3329,7 @@ function useSupplyController() {
|
|
|
3130
3329
|
res.json({ message: "Supply deleted successfully." });
|
|
3131
3330
|
return;
|
|
3132
3331
|
} catch (error2) {
|
|
3133
|
-
|
|
3332
|
+
logger20.log({ level: "error", message: error2.message });
|
|
3134
3333
|
next(error2);
|
|
3135
3334
|
return;
|
|
3136
3335
|
}
|
|
@@ -3138,14 +3337,82 @@ function useSupplyController() {
|
|
|
3138
3337
|
return {
|
|
3139
3338
|
createSupply,
|
|
3140
3339
|
getSupplies,
|
|
3340
|
+
getSupplyById,
|
|
3141
3341
|
updateSupply,
|
|
3142
3342
|
deleteSupply
|
|
3143
3343
|
};
|
|
3144
3344
|
}
|
|
3345
|
+
|
|
3346
|
+
// src/services/hygiene-stock.service.ts
|
|
3347
|
+
import { NotFoundError as NotFoundError5, useAtlas as useAtlas10 } from "@iservice365/node-server-utils";
|
|
3348
|
+
function useStockService() {
|
|
3349
|
+
const { createStock: _createStock } = useStockRepository();
|
|
3350
|
+
const { getSupplyById, updateSupply } = useSupplyRepository();
|
|
3351
|
+
async function createStock(value) {
|
|
3352
|
+
const session = useAtlas10.getClient()?.startSession();
|
|
3353
|
+
try {
|
|
3354
|
+
session?.startTransaction();
|
|
3355
|
+
const { qty, ...stockData } = value;
|
|
3356
|
+
const supply = await getSupplyById(value.supply);
|
|
3357
|
+
if (!supply || supply.qty === void 0) {
|
|
3358
|
+
throw new NotFoundError5("Supply not found.");
|
|
3359
|
+
}
|
|
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
|
+
await session?.commitTransaction();
|
|
3367
|
+
return createdStock;
|
|
3368
|
+
} catch (error) {
|
|
3369
|
+
await session?.abortTransaction();
|
|
3370
|
+
throw error;
|
|
3371
|
+
} finally {
|
|
3372
|
+
await session?.endSession();
|
|
3373
|
+
}
|
|
3374
|
+
}
|
|
3375
|
+
return { createStock };
|
|
3376
|
+
}
|
|
3377
|
+
|
|
3378
|
+
// src/controllers/hygiene-stock.controller.ts
|
|
3379
|
+
import { BadRequestError as BadRequestError20, logger as logger21 } from "@iservice365/node-server-utils";
|
|
3380
|
+
import Joi12 from "joi";
|
|
3381
|
+
function useStockController() {
|
|
3382
|
+
const { createStock: _createStock } = useStockService();
|
|
3383
|
+
async function createStock(req, res, next) {
|
|
3384
|
+
const payload = { ...req.body, ...req.params };
|
|
3385
|
+
const validation = Joi12.object({
|
|
3386
|
+
site: Joi12.string().hex().required(),
|
|
3387
|
+
supply: Joi12.string().hex().required(),
|
|
3388
|
+
qty: Joi12.number().min(0).optional(),
|
|
3389
|
+
remarks: Joi12.string().optional().allow("", null)
|
|
3390
|
+
});
|
|
3391
|
+
const { error } = validation.validate(payload);
|
|
3392
|
+
if (error) {
|
|
3393
|
+
logger21.log({ level: "error", message: error.message });
|
|
3394
|
+
next(new BadRequestError20(error.message));
|
|
3395
|
+
return;
|
|
3396
|
+
}
|
|
3397
|
+
try {
|
|
3398
|
+
const id = await _createStock(payload);
|
|
3399
|
+
res.status(201).json({ message: "Stock created successfully.", id });
|
|
3400
|
+
return;
|
|
3401
|
+
} catch (error2) {
|
|
3402
|
+
logger21.log({ level: "error", message: error2.message });
|
|
3403
|
+
next(error2);
|
|
3404
|
+
return;
|
|
3405
|
+
}
|
|
3406
|
+
}
|
|
3407
|
+
return {
|
|
3408
|
+
createStock
|
|
3409
|
+
};
|
|
3410
|
+
}
|
|
3145
3411
|
export {
|
|
3146
3412
|
MArea,
|
|
3147
3413
|
MAreaChecklist,
|
|
3148
3414
|
MParentChecklist,
|
|
3415
|
+
MStock,
|
|
3149
3416
|
MSupply,
|
|
3150
3417
|
MUnit,
|
|
3151
3418
|
allowedChecklistStatus,
|
|
@@ -3154,6 +3421,7 @@ export {
|
|
|
3154
3421
|
areaChecklistSchema,
|
|
3155
3422
|
areaSchema,
|
|
3156
3423
|
parentChecklistSchema,
|
|
3424
|
+
stockSchema,
|
|
3157
3425
|
supplySchema,
|
|
3158
3426
|
unitSchema,
|
|
3159
3427
|
useAreaChecklistController,
|
|
@@ -3164,8 +3432,12 @@ export {
|
|
|
3164
3432
|
useAreaService,
|
|
3165
3433
|
useParentChecklistController,
|
|
3166
3434
|
useParentChecklistRepo,
|
|
3435
|
+
useStockController,
|
|
3436
|
+
useStockRepository,
|
|
3437
|
+
useStockService,
|
|
3167
3438
|
useSupplyController,
|
|
3168
3439
|
useSupplyRepository,
|
|
3440
|
+
useSupplyService,
|
|
3169
3441
|
useUnitController,
|
|
3170
3442
|
useUnitRepository,
|
|
3171
3443
|
useUnitService
|