@goweekdays/core 2.15.9 → 2.15.10
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 +23 -4
- package/dist/index.js +888 -765
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +797 -669
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22578,19 +22578,36 @@ var schemaAssetItemCreate = import_joi96.default.object({
|
|
|
22578
22578
|
}, "subcategory-requires-category");
|
|
22579
22579
|
var schemaAssetItemUpdate = import_joi96.default.object({
|
|
22580
22580
|
name: import_joi96.default.string().optional(),
|
|
22581
|
+
sku: import_joi96.default.string().optional().allow("", null),
|
|
22582
|
+
price: import_joi96.default.number().min(0).optional().allow("", null),
|
|
22583
|
+
unit: import_joi96.default.string().optional(),
|
|
22581
22584
|
description: import_joi96.default.string().optional().allow("", null),
|
|
22582
22585
|
assetCategory: import_joi96.default.string().valid(...assetItemCategories).optional(),
|
|
22583
|
-
assetClass: import_joi96.default.string().valid(...assetItemClasses).optional(),
|
|
22586
|
+
assetClass: import_joi96.default.string().valid(...assetItemClasses).optional().allow("", null),
|
|
22587
|
+
trackingType: import_joi96.default.string().valid(...assetItemTrackingTypes).optional(),
|
|
22588
|
+
departmentId: import_joi96.default.string().hex().length(24).optional(),
|
|
22589
|
+
departmentName: import_joi96.default.string().optional(),
|
|
22590
|
+
categoryId: import_joi96.default.string().hex().length(24).optional().allow("", null),
|
|
22591
|
+
categoryName: import_joi96.default.string().optional().allow("", null),
|
|
22592
|
+
subcategoryId: import_joi96.default.string().hex().length(24).optional().allow("", null),
|
|
22593
|
+
subcategoryName: import_joi96.default.string().optional().allow("", null),
|
|
22594
|
+
categoryPath: import_joi96.default.string().optional().allow("", null),
|
|
22584
22595
|
brand: import_joi96.default.string().optional().allow("", null),
|
|
22585
|
-
sku: import_joi96.default.string().optional().allow("", null),
|
|
22586
|
-
price: import_joi96.default.number().min(0).optional().allow("", null),
|
|
22587
22596
|
tags: import_joi96.default.array().items(
|
|
22588
22597
|
import_joi96.default.object({
|
|
22589
22598
|
id: import_joi96.default.string().required(),
|
|
22590
22599
|
name: import_joi96.default.string().required()
|
|
22591
22600
|
})
|
|
22592
22601
|
).optional(),
|
|
22593
|
-
|
|
22602
|
+
isPublic: import_joi96.default.boolean().optional(),
|
|
22603
|
+
updatedAt: import_joi96.default.date().optional()
|
|
22604
|
+
}).custom((value, helpers) => {
|
|
22605
|
+
if (value.subcategoryId && !value.categoryId) {
|
|
22606
|
+
return helpers.error("any.custom", {
|
|
22607
|
+
message: "categoryId is required when subcategoryId is provided."
|
|
22608
|
+
});
|
|
22609
|
+
}
|
|
22610
|
+
return value;
|
|
22594
22611
|
});
|
|
22595
22612
|
function modelAssetItem(data) {
|
|
22596
22613
|
const { error } = schemaAssetItem.validate(data);
|
|
@@ -22693,6 +22710,7 @@ function useAssetItemRepo() {
|
|
|
22693
22710
|
{ key: { trackingType: 1 } },
|
|
22694
22711
|
{ key: { status: 1 } },
|
|
22695
22712
|
{ key: { name: "text" } },
|
|
22713
|
+
{ key: { public: 1 } },
|
|
22696
22714
|
{
|
|
22697
22715
|
key: {
|
|
22698
22716
|
orgId: 1,
|
|
@@ -22737,10 +22755,14 @@ function useAssetItemRepo() {
|
|
|
22737
22755
|
categoryId = "",
|
|
22738
22756
|
subcategoryId = "",
|
|
22739
22757
|
brand = "",
|
|
22740
|
-
tags = []
|
|
22758
|
+
tags = [],
|
|
22759
|
+
isPublic = false
|
|
22741
22760
|
} = {}) {
|
|
22742
22761
|
page = page > 0 ? page - 1 : 0;
|
|
22743
22762
|
const query = { status: status2 };
|
|
22763
|
+
if (isPublic) {
|
|
22764
|
+
query.isPublic = true;
|
|
22765
|
+
}
|
|
22744
22766
|
if (search) {
|
|
22745
22767
|
query.$text = { $search: search };
|
|
22746
22768
|
}
|
|
@@ -22781,7 +22803,8 @@ function useAssetItemRepo() {
|
|
|
22781
22803
|
subcategoryId,
|
|
22782
22804
|
brand,
|
|
22783
22805
|
tags: tags.join(","),
|
|
22784
|
-
tag: "getAll"
|
|
22806
|
+
tag: "getAll",
|
|
22807
|
+
public: isPublic ? "true" : "false"
|
|
22785
22808
|
});
|
|
22786
22809
|
try {
|
|
22787
22810
|
const cached = await repo.getCache(cacheKey);
|
|
@@ -22826,10 +22849,16 @@ function useAssetItemRepo() {
|
|
|
22826
22849
|
}
|
|
22827
22850
|
}
|
|
22828
22851
|
async function updateById(id, value) {
|
|
22852
|
+
const { error, value: validatedValue } = schemaAssetItemUpdate.validate(value);
|
|
22853
|
+
if (error) {
|
|
22854
|
+
throw new import_utils116.BadRequestError(
|
|
22855
|
+
`Invalid asset item update data: ${error.message}`
|
|
22856
|
+
);
|
|
22857
|
+
}
|
|
22829
22858
|
try {
|
|
22830
22859
|
const result = await repo.collection.findOneAndUpdate(
|
|
22831
22860
|
{ _id: new import_mongodb59.ObjectId(id) },
|
|
22832
|
-
{ $set: { ...
|
|
22861
|
+
{ $set: { ...validatedValue, updatedAt: /* @__PURE__ */ new Date() } },
|
|
22833
22862
|
{ returnDocument: "after" }
|
|
22834
22863
|
);
|
|
22835
22864
|
if (!result) {
|
|
@@ -22837,9 +22866,9 @@ function useAssetItemRepo() {
|
|
|
22837
22866
|
}
|
|
22838
22867
|
repo.delCachedData();
|
|
22839
22868
|
return result;
|
|
22840
|
-
} catch (
|
|
22841
|
-
if (
|
|
22842
|
-
throw
|
|
22869
|
+
} catch (error2) {
|
|
22870
|
+
if (error2 instanceof import_utils116.AppError)
|
|
22871
|
+
throw error2;
|
|
22843
22872
|
throw new import_utils116.InternalServerError("Failed to update asset item.");
|
|
22844
22873
|
}
|
|
22845
22874
|
}
|
|
@@ -22894,7 +22923,7 @@ function useAssetItemRepo() {
|
|
|
22894
22923
|
}
|
|
22895
22924
|
|
|
22896
22925
|
// src/resources/asset-item/asset.item.service.ts
|
|
22897
|
-
var
|
|
22926
|
+
var import_utils126 = require("@goweekdays/utils");
|
|
22898
22927
|
|
|
22899
22928
|
// src/resources/tag/tag.repository.ts
|
|
22900
22929
|
var import_utils117 = require("@goweekdays/utils");
|
|
@@ -23554,246 +23583,187 @@ function useCategoryRepo() {
|
|
|
23554
23583
|
};
|
|
23555
23584
|
}
|
|
23556
23585
|
|
|
23557
|
-
// src/resources/asset-item/
|
|
23558
|
-
|
|
23559
|
-
|
|
23560
|
-
|
|
23561
|
-
|
|
23562
|
-
|
|
23563
|
-
|
|
23564
|
-
|
|
23565
|
-
|
|
23566
|
-
|
|
23567
|
-
|
|
23568
|
-
|
|
23569
|
-
|
|
23570
|
-
|
|
23571
|
-
|
|
23572
|
-
|
|
23573
|
-
|
|
23574
|
-
|
|
23575
|
-
|
|
23576
|
-
|
|
23577
|
-
|
|
23578
|
-
|
|
23579
|
-
|
|
23580
|
-
|
|
23581
|
-
|
|
23582
|
-
|
|
23583
|
-
|
|
23584
|
-
|
|
23585
|
-
|
|
23586
|
-
|
|
23587
|
-
|
|
23588
|
-
|
|
23589
|
-
|
|
23590
|
-
|
|
23591
|
-
|
|
23592
|
-
|
|
23593
|
-
|
|
23594
|
-
}
|
|
23595
|
-
}
|
|
23596
|
-
return resolvedTags;
|
|
23586
|
+
// src/resources/asset-item-movement/stock.movement.model.ts
|
|
23587
|
+
var import_joi100 = __toESM(require("joi"));
|
|
23588
|
+
var import_mongodb64 = require("mongodb");
|
|
23589
|
+
var stockMovementTypes = [
|
|
23590
|
+
"in",
|
|
23591
|
+
"out",
|
|
23592
|
+
"transfer",
|
|
23593
|
+
"adjustment",
|
|
23594
|
+
"conversion"
|
|
23595
|
+
];
|
|
23596
|
+
var stockMovementReferenceTypes = [
|
|
23597
|
+
"purchase",
|
|
23598
|
+
"sale",
|
|
23599
|
+
"transfer",
|
|
23600
|
+
"manual",
|
|
23601
|
+
"conversion"
|
|
23602
|
+
];
|
|
23603
|
+
var schemaStockMovement = import_joi100.default.object({
|
|
23604
|
+
itemId: import_joi100.default.string().hex().length(24).required(),
|
|
23605
|
+
type: import_joi100.default.string().valid(...stockMovementTypes).required(),
|
|
23606
|
+
quantity: import_joi100.default.number().positive().required(),
|
|
23607
|
+
unitCost: import_joi100.default.number().min(0).optional().allow(null),
|
|
23608
|
+
totalCost: import_joi100.default.number().min(0).optional().allow(null),
|
|
23609
|
+
reference: import_joi100.default.object({
|
|
23610
|
+
type: import_joi100.default.string().valid(...stockMovementReferenceTypes).required(),
|
|
23611
|
+
id: import_joi100.default.string().optional().allow("", null)
|
|
23612
|
+
}).optional().allow(null),
|
|
23613
|
+
fromLocationId: import_joi100.default.string().optional().allow("", null),
|
|
23614
|
+
toLocationId: import_joi100.default.string().optional().allow("", null),
|
|
23615
|
+
fromItemId: import_joi100.default.string().hex().length(24).optional().allow("", null),
|
|
23616
|
+
toItemId: import_joi100.default.string().hex().length(24).optional().allow("", null),
|
|
23617
|
+
reason: import_joi100.default.string().optional().allow("", null)
|
|
23618
|
+
});
|
|
23619
|
+
function modelStockMovement(data) {
|
|
23620
|
+
const { error } = schemaStockMovement.validate(data);
|
|
23621
|
+
if (error) {
|
|
23622
|
+
throw new Error(`Invalid stock movement data: ${error.message}`);
|
|
23597
23623
|
}
|
|
23598
|
-
|
|
23599
|
-
const session = import_utils120.useAtlas.getClient()?.startSession();
|
|
23600
|
-
if (!session) {
|
|
23601
|
-
throw new import_utils120.InternalServerError(
|
|
23602
|
-
"Unable to start session for asset item service."
|
|
23603
|
-
);
|
|
23604
|
-
}
|
|
23624
|
+
if (data.itemId && typeof data.itemId === "string") {
|
|
23605
23625
|
try {
|
|
23606
|
-
|
|
23607
|
-
|
|
23608
|
-
|
|
23609
|
-
if (value.categoryId) {
|
|
23610
|
-
const category = await categoryRepo.getById(value.categoryId);
|
|
23611
|
-
value.categoryName = category.displayName;
|
|
23612
|
-
}
|
|
23613
|
-
if (value.subcategoryId) {
|
|
23614
|
-
const subcategory = await categoryRepo.getById(value.subcategoryId);
|
|
23615
|
-
value.subcategoryName = subcategory.displayName;
|
|
23616
|
-
}
|
|
23617
|
-
const categoryPath = buildCategoryPath(
|
|
23618
|
-
value.departmentName,
|
|
23619
|
-
value.categoryName ?? "",
|
|
23620
|
-
value.subcategoryName ?? ""
|
|
23621
|
-
);
|
|
23622
|
-
value.categoryPath = categoryPath;
|
|
23623
|
-
const resolvedTags = value.tags.length ? await resolveTags(
|
|
23624
|
-
value.tags,
|
|
23625
|
-
value.orgId,
|
|
23626
|
-
value.categoryPath,
|
|
23627
|
-
session
|
|
23628
|
-
) : [];
|
|
23629
|
-
const assetItem = {
|
|
23630
|
-
...value,
|
|
23631
|
-
tags: resolvedTags
|
|
23632
|
-
};
|
|
23633
|
-
const assetItemId = await assetItemRepo.add(assetItem, session);
|
|
23634
|
-
await session.commitTransaction();
|
|
23635
|
-
return assetItemId;
|
|
23636
|
-
} catch (error) {
|
|
23637
|
-
await session.abortTransaction();
|
|
23638
|
-
if (error instanceof import_utils120.AppError)
|
|
23639
|
-
throw error;
|
|
23640
|
-
throw new import_utils120.InternalServerError("Failed to create asset item.");
|
|
23641
|
-
} finally {
|
|
23642
|
-
session.endSession();
|
|
23626
|
+
data.itemId = new import_mongodb64.ObjectId(data.itemId);
|
|
23627
|
+
} catch {
|
|
23628
|
+
throw new Error(`Invalid itemId format: ${data.itemId}`);
|
|
23643
23629
|
}
|
|
23644
23630
|
}
|
|
23645
23631
|
return {
|
|
23646
|
-
|
|
23632
|
+
_id: data._id,
|
|
23633
|
+
itemId: data.itemId,
|
|
23634
|
+
type: data.type,
|
|
23635
|
+
quantity: data.quantity,
|
|
23636
|
+
unitCost: data.unitCost ?? 0,
|
|
23637
|
+
totalCost: data.totalCost ?? 0,
|
|
23638
|
+
reference: data.reference ?? void 0,
|
|
23639
|
+
fromLocationId: data.fromLocationId ?? "",
|
|
23640
|
+
toLocationId: data.toLocationId ?? "",
|
|
23641
|
+
fromItemId: data.fromItemId ?? "",
|
|
23642
|
+
toItemId: data.toItemId ?? "",
|
|
23643
|
+
reason: data.reason ?? "",
|
|
23644
|
+
createdAt: data.createdAt ?? /* @__PURE__ */ new Date()
|
|
23647
23645
|
};
|
|
23648
23646
|
}
|
|
23649
23647
|
|
|
23650
|
-
// src/resources/asset-item/
|
|
23651
|
-
var
|
|
23652
|
-
var
|
|
23653
|
-
|
|
23654
|
-
|
|
23655
|
-
|
|
23656
|
-
|
|
23657
|
-
status: import_joi100.default.string().valid(...assetItemStatuses).optional().allow("", null),
|
|
23658
|
-
assetCategory: import_joi100.default.string().valid(...assetItemCategories).optional().allow("", null),
|
|
23659
|
-
trackingType: import_joi100.default.string().valid(...assetItemTrackingTypes).optional().allow("", null),
|
|
23660
|
-
purpose: import_joi100.default.string().valid(...assetItemPurposes).optional().allow("", null),
|
|
23661
|
-
departmentId: import_joi100.default.string().optional().allow("", null),
|
|
23662
|
-
categoryId: import_joi100.default.string().optional().allow("", null),
|
|
23663
|
-
subcategoryId: import_joi100.default.string().optional().allow("", null),
|
|
23664
|
-
brand: import_joi100.default.string().optional().allow("", null),
|
|
23665
|
-
tags: import_joi100.default.string().optional().allow("", null)
|
|
23666
|
-
});
|
|
23667
|
-
var idParamSchema2 = import_joi100.default.object({
|
|
23668
|
-
id: import_joi100.default.string().hex().length(24).required()
|
|
23669
|
-
});
|
|
23670
|
-
function useAssetItemController() {
|
|
23671
|
-
const repo = useAssetItemRepo();
|
|
23672
|
-
const service = useAssetItemService();
|
|
23673
|
-
async function add(req, res, next) {
|
|
23648
|
+
// src/resources/asset-item-movement/stock.movement.repository.ts
|
|
23649
|
+
var import_utils120 = require("@goweekdays/utils");
|
|
23650
|
+
var import_mongodb65 = require("mongodb");
|
|
23651
|
+
function useStockMovementRepo() {
|
|
23652
|
+
const namespace_collection = "stock.movements";
|
|
23653
|
+
const repo = (0, import_utils120.useRepo)(namespace_collection);
|
|
23654
|
+
async function createIndexes() {
|
|
23674
23655
|
try {
|
|
23675
|
-
|
|
23676
|
-
|
|
23677
|
-
|
|
23678
|
-
|
|
23679
|
-
|
|
23680
|
-
|
|
23681
|
-
res.status(201).json({
|
|
23682
|
-
message: "Asset item created successfully.",
|
|
23683
|
-
assetItemId
|
|
23684
|
-
});
|
|
23656
|
+
await repo.collection.createIndexes([
|
|
23657
|
+
{ key: { itemId: 1 } },
|
|
23658
|
+
{ key: { createdAt: -1 } },
|
|
23659
|
+
{ key: { itemId: 1, createdAt: -1 } },
|
|
23660
|
+
{ key: { type: 1 } }
|
|
23661
|
+
]);
|
|
23685
23662
|
} catch (error) {
|
|
23686
|
-
|
|
23663
|
+
throw new import_utils120.BadRequestError("Failed to create stock movement indexes.");
|
|
23687
23664
|
}
|
|
23688
23665
|
}
|
|
23689
|
-
async function
|
|
23690
|
-
const { error } = paginationSchema3.validate(req.query);
|
|
23691
|
-
if (error) {
|
|
23692
|
-
next(new import_utils121.BadRequestError(error.message));
|
|
23693
|
-
return;
|
|
23694
|
-
}
|
|
23695
|
-
const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
|
|
23696
|
-
const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
|
|
23697
|
-
const search = req.query.search ?? "";
|
|
23698
|
-
const status2 = req.query.status ?? "active";
|
|
23699
|
-
const assetCategory = req.query.assetCategory ?? "";
|
|
23700
|
-
const trackingType = req.query.trackingType ?? "";
|
|
23701
|
-
const purpose = req.query.purpose ?? "";
|
|
23702
|
-
const departmentId = req.query.departmentId ?? "";
|
|
23703
|
-
const categoryId = req.query.categoryId ?? "";
|
|
23704
|
-
const subcategoryId = req.query.subcategoryId ?? "";
|
|
23705
|
-
const brand = req.query.brand ?? "";
|
|
23706
|
-
const tagsParam = req.query.tags ?? "";
|
|
23707
|
-
const tags = tagsParam ? tagsParam.split(",").filter(Boolean) : [];
|
|
23708
|
-
if (!isFinite(page)) {
|
|
23709
|
-
next(new import_utils121.BadRequestError("Invalid page number."));
|
|
23710
|
-
return;
|
|
23711
|
-
}
|
|
23712
|
-
if (!isFinite(limit)) {
|
|
23713
|
-
next(new import_utils121.BadRequestError("Invalid limit number."));
|
|
23714
|
-
return;
|
|
23715
|
-
}
|
|
23666
|
+
async function add(value, session) {
|
|
23716
23667
|
try {
|
|
23717
|
-
|
|
23718
|
-
|
|
23719
|
-
|
|
23720
|
-
|
|
23721
|
-
|
|
23722
|
-
|
|
23723
|
-
|
|
23724
|
-
purpose,
|
|
23725
|
-
departmentId,
|
|
23726
|
-
categoryId,
|
|
23727
|
-
subcategoryId,
|
|
23728
|
-
brand,
|
|
23729
|
-
tags
|
|
23730
|
-
});
|
|
23731
|
-
res.json(results);
|
|
23732
|
-
} catch (error2) {
|
|
23733
|
-
next(error2);
|
|
23668
|
+
value = modelStockMovement(value);
|
|
23669
|
+
const res = await repo.collection.insertOne(value, { session });
|
|
23670
|
+
repo.delCachedData();
|
|
23671
|
+
return res.insertedId;
|
|
23672
|
+
} catch (error) {
|
|
23673
|
+
import_utils120.logger.log({ level: "error", message: error.message });
|
|
23674
|
+
throw new import_utils120.InternalServerError("Failed to create stock movement.");
|
|
23734
23675
|
}
|
|
23735
23676
|
}
|
|
23736
|
-
async function
|
|
23737
|
-
|
|
23738
|
-
|
|
23739
|
-
|
|
23740
|
-
|
|
23677
|
+
async function getByItemId({
|
|
23678
|
+
itemId,
|
|
23679
|
+
type = "",
|
|
23680
|
+
page = 1,
|
|
23681
|
+
limit = 10
|
|
23682
|
+
}) {
|
|
23683
|
+
page = page > 0 ? page - 1 : 0;
|
|
23684
|
+
const query = {
|
|
23685
|
+
itemId: new import_mongodb65.ObjectId(itemId)
|
|
23686
|
+
};
|
|
23687
|
+
if (type) {
|
|
23688
|
+
query.type = type;
|
|
23741
23689
|
}
|
|
23690
|
+
const cacheKey = (0, import_utils120.makeCacheKey)(namespace_collection, {
|
|
23691
|
+
itemId,
|
|
23692
|
+
type,
|
|
23693
|
+
page,
|
|
23694
|
+
limit,
|
|
23695
|
+
tag: "byItemId"
|
|
23696
|
+
});
|
|
23742
23697
|
try {
|
|
23743
|
-
const
|
|
23744
|
-
|
|
23745
|
-
|
|
23746
|
-
|
|
23747
|
-
|
|
23748
|
-
|
|
23749
|
-
|
|
23750
|
-
|
|
23751
|
-
|
|
23752
|
-
|
|
23753
|
-
|
|
23754
|
-
|
|
23755
|
-
|
|
23756
|
-
|
|
23757
|
-
|
|
23758
|
-
|
|
23698
|
+
const cached = await repo.getCache(cacheKey);
|
|
23699
|
+
if (cached)
|
|
23700
|
+
return cached;
|
|
23701
|
+
const items = await repo.collection.aggregate([
|
|
23702
|
+
{ $match: query },
|
|
23703
|
+
{ $sort: { createdAt: -1 } },
|
|
23704
|
+
{ $skip: page * limit },
|
|
23705
|
+
{ $limit: limit }
|
|
23706
|
+
]).toArray();
|
|
23707
|
+
const length = await repo.collection.countDocuments(query);
|
|
23708
|
+
const data = (0, import_utils120.paginate)(items, page, limit, length);
|
|
23709
|
+
repo.setCache(cacheKey, data, 600);
|
|
23710
|
+
return data;
|
|
23711
|
+
} catch (error) {
|
|
23712
|
+
import_utils120.logger.log({ level: "error", message: `${error}` });
|
|
23713
|
+
throw error;
|
|
23759
23714
|
}
|
|
23715
|
+
}
|
|
23716
|
+
async function getById(id) {
|
|
23717
|
+
const cacheKey = (0, import_utils120.makeCacheKey)(namespace_collection, {
|
|
23718
|
+
id,
|
|
23719
|
+
tag: "by-id"
|
|
23720
|
+
});
|
|
23760
23721
|
try {
|
|
23761
|
-
const
|
|
23762
|
-
|
|
23763
|
-
|
|
23764
|
-
|
|
23722
|
+
const cached = await repo.getCache(cacheKey);
|
|
23723
|
+
if (cached)
|
|
23724
|
+
return cached;
|
|
23725
|
+
const result = await repo.collection.findOne({
|
|
23726
|
+
_id: new import_mongodb65.ObjectId(id)
|
|
23765
23727
|
});
|
|
23728
|
+
if (!result) {
|
|
23729
|
+
throw new import_utils120.BadRequestError("Stock movement not found.");
|
|
23730
|
+
}
|
|
23731
|
+
repo.setCache(cacheKey, result, 300);
|
|
23732
|
+
return result;
|
|
23766
23733
|
} catch (error) {
|
|
23767
|
-
|
|
23734
|
+
if (error instanceof import_utils120.AppError)
|
|
23735
|
+
throw error;
|
|
23736
|
+
throw new import_utils120.InternalServerError("Failed to get stock movement.");
|
|
23768
23737
|
}
|
|
23769
23738
|
}
|
|
23770
|
-
async function
|
|
23771
|
-
const { error } = idParamSchema2.validate(req.params);
|
|
23772
|
-
if (error) {
|
|
23773
|
-
next(new import_utils121.BadRequestError(error.message));
|
|
23774
|
-
return;
|
|
23775
|
-
}
|
|
23739
|
+
async function countByItemId(itemId) {
|
|
23776
23740
|
try {
|
|
23777
|
-
await repo.
|
|
23778
|
-
|
|
23779
|
-
message: "Asset item deleted successfully."
|
|
23741
|
+
return await repo.collection.countDocuments({
|
|
23742
|
+
itemId: new import_mongodb65.ObjectId(itemId)
|
|
23780
23743
|
});
|
|
23781
|
-
} catch (
|
|
23782
|
-
|
|
23744
|
+
} catch (error) {
|
|
23745
|
+
throw new import_utils120.InternalServerError("Failed to count stock movements.");
|
|
23783
23746
|
}
|
|
23784
23747
|
}
|
|
23785
23748
|
return {
|
|
23749
|
+
createIndexes,
|
|
23786
23750
|
add,
|
|
23787
|
-
|
|
23751
|
+
getByItemId,
|
|
23788
23752
|
getById,
|
|
23789
|
-
|
|
23790
|
-
deleteById
|
|
23753
|
+
countByItemId
|
|
23791
23754
|
};
|
|
23792
23755
|
}
|
|
23793
23756
|
|
|
23757
|
+
// src/resources/asset-item-movement/stock.movement.service.ts
|
|
23758
|
+
var import_utils122 = require("@goweekdays/utils");
|
|
23759
|
+
var import_utils123 = require("@goweekdays/utils");
|
|
23760
|
+
|
|
23761
|
+
// src/resources/asset-item-unit/asset.unit.repository.ts
|
|
23762
|
+
var import_utils121 = require("@goweekdays/utils");
|
|
23763
|
+
|
|
23794
23764
|
// src/resources/asset-item-unit/asset.unit.model.ts
|
|
23795
23765
|
var import_joi101 = __toESM(require("joi"));
|
|
23796
|
-
var
|
|
23766
|
+
var import_mongodb66 = require("mongodb");
|
|
23797
23767
|
var assetUnitStatuses = [
|
|
23798
23768
|
"available",
|
|
23799
23769
|
"assigned",
|
|
@@ -23823,7 +23793,7 @@ function modelAssetUnit(data) {
|
|
|
23823
23793
|
}
|
|
23824
23794
|
if (data.itemId && typeof data.itemId === "string") {
|
|
23825
23795
|
try {
|
|
23826
|
-
data.itemId = new
|
|
23796
|
+
data.itemId = new import_mongodb66.ObjectId(data.itemId);
|
|
23827
23797
|
} catch {
|
|
23828
23798
|
throw new Error(`Invalid itemId format: ${data.itemId}`);
|
|
23829
23799
|
}
|
|
@@ -23842,11 +23812,10 @@ function modelAssetUnit(data) {
|
|
|
23842
23812
|
}
|
|
23843
23813
|
|
|
23844
23814
|
// src/resources/asset-item-unit/asset.unit.repository.ts
|
|
23845
|
-
var
|
|
23846
|
-
var import_mongodb65 = require("mongodb");
|
|
23815
|
+
var import_mongodb67 = require("mongodb");
|
|
23847
23816
|
function useAssetUnitRepo() {
|
|
23848
23817
|
const namespace_collection = "asset.units";
|
|
23849
|
-
const repo = (0,
|
|
23818
|
+
const repo = (0, import_utils121.useRepo)(namespace_collection);
|
|
23850
23819
|
async function createIndexes() {
|
|
23851
23820
|
try {
|
|
23852
23821
|
await repo.collection.createIndexes([
|
|
@@ -23856,7 +23825,7 @@ function useAssetUnitRepo() {
|
|
|
23856
23825
|
{ key: { itemId: 1, status: 1 } }
|
|
23857
23826
|
]);
|
|
23858
23827
|
} catch (error) {
|
|
23859
|
-
throw new
|
|
23828
|
+
throw new import_utils121.BadRequestError("Failed to create asset unit indexes.");
|
|
23860
23829
|
}
|
|
23861
23830
|
}
|
|
23862
23831
|
async function add(value, session) {
|
|
@@ -23866,8 +23835,8 @@ function useAssetUnitRepo() {
|
|
|
23866
23835
|
repo.delCachedData();
|
|
23867
23836
|
return res.insertedId;
|
|
23868
23837
|
} catch (error) {
|
|
23869
|
-
|
|
23870
|
-
throw new
|
|
23838
|
+
import_utils121.logger.log({ level: "error", message: error.message });
|
|
23839
|
+
throw new import_utils121.InternalServerError("Failed to create asset unit.");
|
|
23871
23840
|
}
|
|
23872
23841
|
}
|
|
23873
23842
|
async function getByItemId({
|
|
@@ -23878,12 +23847,12 @@ function useAssetUnitRepo() {
|
|
|
23878
23847
|
}) {
|
|
23879
23848
|
page = page > 0 ? page - 1 : 0;
|
|
23880
23849
|
const query = {
|
|
23881
|
-
itemId: new
|
|
23850
|
+
itemId: new import_mongodb67.ObjectId(itemId)
|
|
23882
23851
|
};
|
|
23883
23852
|
if (status2) {
|
|
23884
23853
|
query.status = status2;
|
|
23885
23854
|
}
|
|
23886
|
-
const cacheKey = (0,
|
|
23855
|
+
const cacheKey = (0, import_utils121.makeCacheKey)(namespace_collection, {
|
|
23887
23856
|
itemId,
|
|
23888
23857
|
status: status2,
|
|
23889
23858
|
page,
|
|
@@ -23901,16 +23870,16 @@ function useAssetUnitRepo() {
|
|
|
23901
23870
|
{ $limit: limit }
|
|
23902
23871
|
]).toArray();
|
|
23903
23872
|
const length = await repo.collection.countDocuments(query);
|
|
23904
|
-
const data = (0,
|
|
23873
|
+
const data = (0, import_utils121.paginate)(items, page, limit, length);
|
|
23905
23874
|
repo.setCache(cacheKey, data, 600);
|
|
23906
23875
|
return data;
|
|
23907
23876
|
} catch (error) {
|
|
23908
|
-
|
|
23877
|
+
import_utils121.logger.log({ level: "error", message: `${error}` });
|
|
23909
23878
|
throw error;
|
|
23910
23879
|
}
|
|
23911
23880
|
}
|
|
23912
23881
|
async function getById(id) {
|
|
23913
|
-
const cacheKey = (0,
|
|
23882
|
+
const cacheKey = (0, import_utils121.makeCacheKey)(namespace_collection, {
|
|
23914
23883
|
id,
|
|
23915
23884
|
tag: "by-id"
|
|
23916
23885
|
});
|
|
@@ -23919,45 +23888,54 @@ function useAssetUnitRepo() {
|
|
|
23919
23888
|
if (cached)
|
|
23920
23889
|
return cached;
|
|
23921
23890
|
const result = await repo.collection.findOne({
|
|
23922
|
-
_id: new
|
|
23891
|
+
_id: new import_mongodb67.ObjectId(id)
|
|
23923
23892
|
});
|
|
23924
23893
|
if (!result) {
|
|
23925
|
-
throw new
|
|
23894
|
+
throw new import_utils121.BadRequestError("Asset unit not found.");
|
|
23926
23895
|
}
|
|
23927
23896
|
repo.setCache(cacheKey, result, 300);
|
|
23928
23897
|
return result;
|
|
23929
23898
|
} catch (error) {
|
|
23930
|
-
if (error instanceof
|
|
23899
|
+
if (error instanceof import_utils121.AppError)
|
|
23931
23900
|
throw error;
|
|
23932
|
-
throw new
|
|
23901
|
+
throw new import_utils121.InternalServerError("Failed to get asset unit.");
|
|
23933
23902
|
}
|
|
23934
23903
|
}
|
|
23935
23904
|
async function updateById(id, value, session) {
|
|
23936
23905
|
try {
|
|
23937
23906
|
const result = await repo.collection.findOneAndUpdate(
|
|
23938
|
-
{ _id: new
|
|
23907
|
+
{ _id: new import_mongodb67.ObjectId(id) },
|
|
23939
23908
|
{ $set: { ...value, updatedAt: /* @__PURE__ */ new Date() } },
|
|
23940
23909
|
{ returnDocument: "after", session }
|
|
23941
23910
|
);
|
|
23942
23911
|
if (!result) {
|
|
23943
|
-
throw new
|
|
23912
|
+
throw new import_utils121.BadRequestError("Asset unit not found.");
|
|
23944
23913
|
}
|
|
23945
23914
|
repo.delCachedData();
|
|
23946
23915
|
return result;
|
|
23947
23916
|
} catch (error) {
|
|
23948
|
-
if (error instanceof
|
|
23917
|
+
if (error instanceof import_utils121.AppError)
|
|
23949
23918
|
throw error;
|
|
23950
|
-
throw new
|
|
23919
|
+
throw new import_utils121.InternalServerError("Failed to update asset unit.");
|
|
23920
|
+
}
|
|
23921
|
+
}
|
|
23922
|
+
async function countByItemId(itemId) {
|
|
23923
|
+
try {
|
|
23924
|
+
return await repo.collection.countDocuments({
|
|
23925
|
+
itemId: new import_mongodb67.ObjectId(itemId)
|
|
23926
|
+
});
|
|
23927
|
+
} catch (error) {
|
|
23928
|
+
throw new import_utils121.InternalServerError("Failed to count asset units.");
|
|
23951
23929
|
}
|
|
23952
23930
|
}
|
|
23953
23931
|
async function countByItemIdAndStatus(itemId, status2) {
|
|
23954
23932
|
try {
|
|
23955
23933
|
return await repo.collection.countDocuments({
|
|
23956
|
-
itemId: new
|
|
23934
|
+
itemId: new import_mongodb67.ObjectId(itemId),
|
|
23957
23935
|
status: status2
|
|
23958
23936
|
});
|
|
23959
23937
|
} catch (error) {
|
|
23960
|
-
throw new
|
|
23938
|
+
throw new import_utils121.InternalServerError("Failed to count asset units.");
|
|
23961
23939
|
}
|
|
23962
23940
|
}
|
|
23963
23941
|
return {
|
|
@@ -23966,671 +23944,816 @@ function useAssetUnitRepo() {
|
|
|
23966
23944
|
getByItemId,
|
|
23967
23945
|
getById,
|
|
23968
23946
|
updateById,
|
|
23947
|
+
countByItemId,
|
|
23969
23948
|
countByItemIdAndStatus
|
|
23970
23949
|
};
|
|
23971
23950
|
}
|
|
23972
23951
|
|
|
23973
|
-
// src/resources/asset-item-
|
|
23974
|
-
|
|
23975
|
-
|
|
23976
|
-
|
|
23977
|
-
|
|
23978
|
-
|
|
23979
|
-
|
|
23980
|
-
|
|
23981
|
-
|
|
23982
|
-
|
|
23983
|
-
id: import_joi102.default.string().hex().length(24).required()
|
|
23984
|
-
});
|
|
23985
|
-
function useAssetUnitController() {
|
|
23986
|
-
const repo = useAssetUnitRepo();
|
|
23987
|
-
async function add(req, res, next) {
|
|
23952
|
+
// src/resources/asset-item-movement/stock.movement.service.ts
|
|
23953
|
+
function useStockMovementService() {
|
|
23954
|
+
const movementRepo = useStockMovementRepo();
|
|
23955
|
+
const assetItemRepo = useAssetItemRepo();
|
|
23956
|
+
const assetUnitRepo = useAssetUnitRepo();
|
|
23957
|
+
async function stockIn(value, units) {
|
|
23958
|
+
const item = await assetItemRepo.getById(String(value.itemId));
|
|
23959
|
+
const session = import_utils123.useAtlas.getClient()?.startSession();
|
|
23960
|
+
if (!session)
|
|
23961
|
+
throw new import_utils122.BadRequestError("Failed to start session.");
|
|
23988
23962
|
try {
|
|
23989
|
-
|
|
23990
|
-
|
|
23991
|
-
|
|
23992
|
-
|
|
23963
|
+
session.startTransaction();
|
|
23964
|
+
value.type = "in";
|
|
23965
|
+
const movementId = await movementRepo.add(value, session);
|
|
23966
|
+
if (item.trackingType === "individual" && units && units.length > 0) {
|
|
23967
|
+
for (const unit of units) {
|
|
23968
|
+
await assetUnitRepo.add(
|
|
23969
|
+
{
|
|
23970
|
+
itemId: value.itemId,
|
|
23971
|
+
serialNumber: unit.serialNumber,
|
|
23972
|
+
plateNumber: unit.plateNumber,
|
|
23973
|
+
status: "available",
|
|
23974
|
+
locationId: value.toLocationId
|
|
23975
|
+
},
|
|
23976
|
+
session
|
|
23977
|
+
);
|
|
23978
|
+
}
|
|
23993
23979
|
}
|
|
23994
|
-
|
|
23995
|
-
|
|
23996
|
-
|
|
23997
|
-
|
|
23998
|
-
|
|
23980
|
+
await assetItemRepo.incrementQuantity(
|
|
23981
|
+
String(value.itemId),
|
|
23982
|
+
value.quantity,
|
|
23983
|
+
session
|
|
23984
|
+
);
|
|
23985
|
+
await session.commitTransaction();
|
|
23986
|
+
return movementId;
|
|
23999
23987
|
} catch (error) {
|
|
24000
|
-
|
|
23988
|
+
await session.abortTransaction();
|
|
23989
|
+
throw error;
|
|
23990
|
+
} finally {
|
|
23991
|
+
await session.endSession();
|
|
24001
23992
|
}
|
|
24002
23993
|
}
|
|
24003
|
-
async function
|
|
24004
|
-
const
|
|
24005
|
-
if (
|
|
24006
|
-
|
|
24007
|
-
return;
|
|
23994
|
+
async function stockOut(value, unitIds) {
|
|
23995
|
+
const item = await assetItemRepo.getById(String(value.itemId));
|
|
23996
|
+
if (item.trackingType === "quantity" && (item.quantityOnHand ?? 0) < value.quantity) {
|
|
23997
|
+
throw new import_utils122.BadRequestError("Insufficient stock.");
|
|
24008
23998
|
}
|
|
24009
|
-
const
|
|
24010
|
-
|
|
24011
|
-
|
|
24012
|
-
const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
|
|
23999
|
+
const session = import_utils123.useAtlas.getClient()?.startSession();
|
|
24000
|
+
if (!session)
|
|
24001
|
+
throw new import_utils122.BadRequestError("Failed to start session.");
|
|
24013
24002
|
try {
|
|
24014
|
-
|
|
24015
|
-
|
|
24016
|
-
|
|
24017
|
-
|
|
24003
|
+
session.startTransaction();
|
|
24004
|
+
value.type = "out";
|
|
24005
|
+
const movementId = await movementRepo.add(value, session);
|
|
24006
|
+
if (item.trackingType === "individual" && unitIds && unitIds.length > 0) {
|
|
24007
|
+
for (const unitId of unitIds) {
|
|
24008
|
+
await assetUnitRepo.updateById(
|
|
24009
|
+
unitId,
|
|
24010
|
+
{ status: "assigned", assignedTo: value.reference?.id },
|
|
24011
|
+
session
|
|
24012
|
+
);
|
|
24013
|
+
}
|
|
24014
|
+
}
|
|
24015
|
+
await assetItemRepo.incrementQuantity(
|
|
24016
|
+
String(value.itemId),
|
|
24017
|
+
-value.quantity,
|
|
24018
|
+
session
|
|
24019
|
+
);
|
|
24020
|
+
await session.commitTransaction();
|
|
24021
|
+
return movementId;
|
|
24022
|
+
} catch (error) {
|
|
24023
|
+
await session.abortTransaction();
|
|
24024
|
+
throw error;
|
|
24025
|
+
} finally {
|
|
24026
|
+
await session.endSession();
|
|
24018
24027
|
}
|
|
24019
24028
|
}
|
|
24020
|
-
async function
|
|
24021
|
-
|
|
24022
|
-
|
|
24023
|
-
|
|
24024
|
-
|
|
24029
|
+
async function transfer(value, unitIds) {
|
|
24030
|
+
if (!value.fromLocationId || !value.toLocationId) {
|
|
24031
|
+
throw new import_utils122.BadRequestError(
|
|
24032
|
+
"Transfer requires both fromLocationId and toLocationId."
|
|
24033
|
+
);
|
|
24025
24034
|
}
|
|
24035
|
+
const item = await assetItemRepo.getById(String(value.itemId));
|
|
24036
|
+
const session = import_utils123.useAtlas.getClient()?.startSession();
|
|
24037
|
+
if (!session)
|
|
24038
|
+
throw new import_utils122.BadRequestError("Failed to start session.");
|
|
24026
24039
|
try {
|
|
24027
|
-
|
|
24028
|
-
|
|
24029
|
-
|
|
24030
|
-
|
|
24040
|
+
session.startTransaction();
|
|
24041
|
+
value.type = "transfer";
|
|
24042
|
+
const movementId = await movementRepo.add(value, session);
|
|
24043
|
+
if (item.trackingType === "individual" && unitIds && unitIds.length > 0) {
|
|
24044
|
+
for (const unitId of unitIds) {
|
|
24045
|
+
await assetUnitRepo.updateById(
|
|
24046
|
+
unitId,
|
|
24047
|
+
{ locationId: value.toLocationId },
|
|
24048
|
+
session
|
|
24049
|
+
);
|
|
24050
|
+
}
|
|
24051
|
+
}
|
|
24052
|
+
await session.commitTransaction();
|
|
24053
|
+
return movementId;
|
|
24054
|
+
} catch (error) {
|
|
24055
|
+
await session.abortTransaction();
|
|
24056
|
+
throw error;
|
|
24057
|
+
} finally {
|
|
24058
|
+
await session.endSession();
|
|
24031
24059
|
}
|
|
24032
24060
|
}
|
|
24033
|
-
async function
|
|
24034
|
-
|
|
24035
|
-
|
|
24036
|
-
next(new import_utils123.BadRequestError(paramError.message));
|
|
24037
|
-
return;
|
|
24038
|
-
}
|
|
24039
|
-
const { error: bodyError } = schemaAssetUnitUpdate.validate(req.body);
|
|
24040
|
-
if (bodyError) {
|
|
24041
|
-
next(new import_utils123.BadRequestError(bodyError.message));
|
|
24042
|
-
return;
|
|
24061
|
+
async function adjustment(value) {
|
|
24062
|
+
if (!value.reason) {
|
|
24063
|
+
throw new import_utils122.BadRequestError("Adjustment requires a reason.");
|
|
24043
24064
|
}
|
|
24065
|
+
const session = import_utils123.useAtlas.getClient()?.startSession();
|
|
24066
|
+
if (!session)
|
|
24067
|
+
throw new import_utils122.BadRequestError("Failed to start session.");
|
|
24044
24068
|
try {
|
|
24045
|
-
|
|
24046
|
-
|
|
24047
|
-
|
|
24048
|
-
|
|
24049
|
-
|
|
24069
|
+
session.startTransaction();
|
|
24070
|
+
value.type = "adjustment";
|
|
24071
|
+
const movementId = await movementRepo.add(value, session);
|
|
24072
|
+
await assetItemRepo.incrementQuantity(
|
|
24073
|
+
String(value.itemId),
|
|
24074
|
+
value.quantity,
|
|
24075
|
+
session
|
|
24076
|
+
);
|
|
24077
|
+
await session.commitTransaction();
|
|
24078
|
+
return movementId;
|
|
24050
24079
|
} catch (error) {
|
|
24051
|
-
|
|
24080
|
+
await session.abortTransaction();
|
|
24081
|
+
throw error;
|
|
24082
|
+
} finally {
|
|
24083
|
+
await session.endSession();
|
|
24052
24084
|
}
|
|
24053
24085
|
}
|
|
24054
|
-
|
|
24055
|
-
|
|
24056
|
-
|
|
24057
|
-
|
|
24058
|
-
|
|
24059
|
-
|
|
24060
|
-
|
|
24061
|
-
|
|
24062
|
-
|
|
24063
|
-
|
|
24064
|
-
|
|
24065
|
-
var stockMovementTypes = [
|
|
24066
|
-
"in",
|
|
24067
|
-
"out",
|
|
24068
|
-
"transfer",
|
|
24069
|
-
"adjustment",
|
|
24070
|
-
"conversion"
|
|
24071
|
-
];
|
|
24072
|
-
var stockMovementReferenceTypes = [
|
|
24073
|
-
"purchase",
|
|
24074
|
-
"sale",
|
|
24075
|
-
"transfer",
|
|
24076
|
-
"manual",
|
|
24077
|
-
"conversion"
|
|
24078
|
-
];
|
|
24079
|
-
var schemaStockMovement = import_joi103.default.object({
|
|
24080
|
-
itemId: import_joi103.default.string().hex().length(24).required(),
|
|
24081
|
-
type: import_joi103.default.string().valid(...stockMovementTypes).required(),
|
|
24082
|
-
quantity: import_joi103.default.number().positive().required(),
|
|
24083
|
-
unitCost: import_joi103.default.number().min(0).optional().allow(null),
|
|
24084
|
-
totalCost: import_joi103.default.number().min(0).optional().allow(null),
|
|
24085
|
-
reference: import_joi103.default.object({
|
|
24086
|
-
type: import_joi103.default.string().valid(...stockMovementReferenceTypes).required(),
|
|
24087
|
-
id: import_joi103.default.string().optional().allow("", null)
|
|
24088
|
-
}).optional().allow(null),
|
|
24089
|
-
fromLocationId: import_joi103.default.string().optional().allow("", null),
|
|
24090
|
-
toLocationId: import_joi103.default.string().optional().allow("", null),
|
|
24091
|
-
fromItemId: import_joi103.default.string().hex().length(24).optional().allow("", null),
|
|
24092
|
-
toItemId: import_joi103.default.string().hex().length(24).optional().allow("", null),
|
|
24093
|
-
reason: import_joi103.default.string().optional().allow("", null)
|
|
24094
|
-
});
|
|
24095
|
-
function modelStockMovement(data) {
|
|
24096
|
-
const { error } = schemaStockMovement.validate(data);
|
|
24097
|
-
if (error) {
|
|
24098
|
-
throw new Error(`Invalid stock movement data: ${error.message}`);
|
|
24099
|
-
}
|
|
24100
|
-
if (data.itemId && typeof data.itemId === "string") {
|
|
24086
|
+
async function conversion(newItem, quantity, unitIds) {
|
|
24087
|
+
const sourceItem = await assetItemRepo.getById(String(newItem.itemRefId));
|
|
24088
|
+
if (!newItem.itemRefId) {
|
|
24089
|
+
throw new import_utils122.BadRequestError("Conversion requires itemRefId.");
|
|
24090
|
+
}
|
|
24091
|
+
if (sourceItem.trackingType === "quantity" && (sourceItem.quantityOnHand ?? 0) < quantity) {
|
|
24092
|
+
throw new import_utils122.BadRequestError("Insufficient stock on source item.");
|
|
24093
|
+
}
|
|
24094
|
+
const session = import_utils123.useAtlas.getClient()?.startSession();
|
|
24095
|
+
if (!session)
|
|
24096
|
+
throw new import_utils122.BadRequestError("Failed to start session.");
|
|
24101
24097
|
try {
|
|
24102
|
-
|
|
24103
|
-
|
|
24104
|
-
|
|
24098
|
+
session.startTransaction();
|
|
24099
|
+
const newItemId = await assetItemRepo.add(newItem, session);
|
|
24100
|
+
const movementData = {
|
|
24101
|
+
itemId: newItem.itemRefId,
|
|
24102
|
+
type: "conversion",
|
|
24103
|
+
quantity,
|
|
24104
|
+
fromItemId: String(newItem.itemRefId),
|
|
24105
|
+
toItemId: String(newItemId),
|
|
24106
|
+
reference: { type: "conversion", id: String(newItemId) }
|
|
24107
|
+
};
|
|
24108
|
+
const movementId = await movementRepo.add(movementData, session);
|
|
24109
|
+
await assetItemRepo.incrementQuantity(
|
|
24110
|
+
String(newItem.itemRefId),
|
|
24111
|
+
-quantity,
|
|
24112
|
+
session
|
|
24113
|
+
);
|
|
24114
|
+
await assetItemRepo.incrementQuantity(
|
|
24115
|
+
String(newItemId),
|
|
24116
|
+
quantity,
|
|
24117
|
+
session
|
|
24118
|
+
);
|
|
24119
|
+
if (sourceItem.trackingType === "individual" && unitIds && unitIds.length > 0) {
|
|
24120
|
+
for (const unitId of unitIds) {
|
|
24121
|
+
await assetUnitRepo.updateById(
|
|
24122
|
+
unitId,
|
|
24123
|
+
{ itemId: String(newItemId) },
|
|
24124
|
+
session
|
|
24125
|
+
);
|
|
24126
|
+
}
|
|
24127
|
+
}
|
|
24128
|
+
await session.commitTransaction();
|
|
24129
|
+
return { movementId, newItemId };
|
|
24130
|
+
} catch (error) {
|
|
24131
|
+
await session.abortTransaction();
|
|
24132
|
+
throw error;
|
|
24133
|
+
} finally {
|
|
24134
|
+
await session.endSession();
|
|
24105
24135
|
}
|
|
24106
24136
|
}
|
|
24107
24137
|
return {
|
|
24108
|
-
|
|
24109
|
-
|
|
24110
|
-
|
|
24111
|
-
|
|
24112
|
-
|
|
24113
|
-
totalCost: data.totalCost ?? 0,
|
|
24114
|
-
reference: data.reference ?? void 0,
|
|
24115
|
-
fromLocationId: data.fromLocationId ?? "",
|
|
24116
|
-
toLocationId: data.toLocationId ?? "",
|
|
24117
|
-
fromItemId: data.fromItemId ?? "",
|
|
24118
|
-
toItemId: data.toItemId ?? "",
|
|
24119
|
-
reason: data.reason ?? "",
|
|
24120
|
-
createdAt: data.createdAt ?? /* @__PURE__ */ new Date()
|
|
24138
|
+
stockIn,
|
|
24139
|
+
stockOut,
|
|
24140
|
+
transfer,
|
|
24141
|
+
adjustment,
|
|
24142
|
+
conversion
|
|
24121
24143
|
};
|
|
24122
24144
|
}
|
|
24123
24145
|
|
|
24124
|
-
// src/resources/asset-item-movement/stock.movement.
|
|
24146
|
+
// src/resources/asset-item-movement/stock.movement.controller.ts
|
|
24147
|
+
var import_joi102 = __toESM(require("joi"));
|
|
24125
24148
|
var import_utils124 = require("@goweekdays/utils");
|
|
24126
|
-
var
|
|
24127
|
-
|
|
24128
|
-
|
|
24129
|
-
|
|
24130
|
-
|
|
24149
|
+
var querySchema = import_joi102.default.object({
|
|
24150
|
+
itemId: import_joi102.default.string().hex().length(24).required(),
|
|
24151
|
+
type: import_joi102.default.string().valid(...stockMovementTypes).optional().allow("", null),
|
|
24152
|
+
page: import_joi102.default.number().min(1).optional().allow("", null),
|
|
24153
|
+
limit: import_joi102.default.number().min(1).optional().allow("", null)
|
|
24154
|
+
});
|
|
24155
|
+
var idParamSchema2 = import_joi102.default.object({
|
|
24156
|
+
id: import_joi102.default.string().hex().length(24).required()
|
|
24157
|
+
});
|
|
24158
|
+
var stockInSchema = import_joi102.default.object({
|
|
24159
|
+
itemId: import_joi102.default.string().hex().length(24).required(),
|
|
24160
|
+
quantity: import_joi102.default.number().positive().required(),
|
|
24161
|
+
unitCost: import_joi102.default.number().min(0).optional().allow(null),
|
|
24162
|
+
totalCost: import_joi102.default.number().min(0).optional().allow(null),
|
|
24163
|
+
reference: import_joi102.default.object({
|
|
24164
|
+
type: import_joi102.default.string().valid("purchase", "sale", "transfer", "manual", "conversion").required(),
|
|
24165
|
+
id: import_joi102.default.string().optional().allow("", null)
|
|
24166
|
+
}).optional().allow(null),
|
|
24167
|
+
toLocationId: import_joi102.default.string().optional().allow("", null),
|
|
24168
|
+
units: import_joi102.default.array().items(
|
|
24169
|
+
import_joi102.default.object({
|
|
24170
|
+
serialNumber: import_joi102.default.string().optional().allow("", null),
|
|
24171
|
+
plateNumber: import_joi102.default.string().optional().allow("", null)
|
|
24172
|
+
})
|
|
24173
|
+
).optional()
|
|
24174
|
+
});
|
|
24175
|
+
var stockOutSchema = import_joi102.default.object({
|
|
24176
|
+
itemId: import_joi102.default.string().hex().length(24).required(),
|
|
24177
|
+
quantity: import_joi102.default.number().positive().required(),
|
|
24178
|
+
unitCost: import_joi102.default.number().min(0).optional().allow(null),
|
|
24179
|
+
totalCost: import_joi102.default.number().min(0).optional().allow(null),
|
|
24180
|
+
reference: import_joi102.default.object({
|
|
24181
|
+
type: import_joi102.default.string().valid("purchase", "sale", "transfer", "manual", "conversion").required(),
|
|
24182
|
+
id: import_joi102.default.string().optional().allow("", null)
|
|
24183
|
+
}).optional().allow(null),
|
|
24184
|
+
fromLocationId: import_joi102.default.string().optional().allow("", null),
|
|
24185
|
+
unitIds: import_joi102.default.array().items(import_joi102.default.string().hex().length(24)).optional()
|
|
24186
|
+
});
|
|
24187
|
+
var transferSchema = import_joi102.default.object({
|
|
24188
|
+
itemId: import_joi102.default.string().hex().length(24).required(),
|
|
24189
|
+
quantity: import_joi102.default.number().positive().required(),
|
|
24190
|
+
fromLocationId: import_joi102.default.string().required(),
|
|
24191
|
+
toLocationId: import_joi102.default.string().required(),
|
|
24192
|
+
reference: import_joi102.default.object({
|
|
24193
|
+
type: import_joi102.default.string().valid("purchase", "sale", "transfer", "manual", "conversion").required(),
|
|
24194
|
+
id: import_joi102.default.string().optional().allow("", null)
|
|
24195
|
+
}).optional().allow(null),
|
|
24196
|
+
unitIds: import_joi102.default.array().items(import_joi102.default.string().hex().length(24)).optional()
|
|
24197
|
+
});
|
|
24198
|
+
var adjustmentSchema = import_joi102.default.object({
|
|
24199
|
+
itemId: import_joi102.default.string().hex().length(24).required(),
|
|
24200
|
+
quantity: import_joi102.default.number().required(),
|
|
24201
|
+
reason: import_joi102.default.string().required(),
|
|
24202
|
+
reference: import_joi102.default.object({
|
|
24203
|
+
type: import_joi102.default.string().valid("purchase", "sale", "transfer", "manual", "conversion").required(),
|
|
24204
|
+
id: import_joi102.default.string().optional().allow("", null)
|
|
24205
|
+
}).optional().allow(null)
|
|
24206
|
+
});
|
|
24207
|
+
var conversionSchema = import_joi102.default.object({
|
|
24208
|
+
quantity: import_joi102.default.number().positive().required(),
|
|
24209
|
+
newItem: import_joi102.default.object({
|
|
24210
|
+
name: import_joi102.default.string().required(),
|
|
24211
|
+
description: import_joi102.default.string().optional().allow("", null),
|
|
24212
|
+
assetCategory: import_joi102.default.string().valid(...assetItemCategories).required(),
|
|
24213
|
+
assetClass: import_joi102.default.string().valid(...assetItemClasses).required(),
|
|
24214
|
+
trackingType: import_joi102.default.string().valid(...assetItemTrackingTypes).required(),
|
|
24215
|
+
purpose: import_joi102.default.string().valid(...assetItemPurposes).required(),
|
|
24216
|
+
itemRefId: import_joi102.default.string().hex().length(24).required(),
|
|
24217
|
+
remarks: import_joi102.default.string().optional().allow("", null),
|
|
24218
|
+
departmentId: import_joi102.default.string().required(),
|
|
24219
|
+
departmentName: import_joi102.default.string().required(),
|
|
24220
|
+
categoryId: import_joi102.default.string().required(),
|
|
24221
|
+
categoryName: import_joi102.default.string().required(),
|
|
24222
|
+
subcategoryId: import_joi102.default.string().required(),
|
|
24223
|
+
subcategoryName: import_joi102.default.string().required(),
|
|
24224
|
+
categoryPath: import_joi102.default.string().required(),
|
|
24225
|
+
brand: import_joi102.default.string().optional().allow("", null),
|
|
24226
|
+
tags: import_joi102.default.array().items(
|
|
24227
|
+
import_joi102.default.object({
|
|
24228
|
+
id: import_joi102.default.string().required(),
|
|
24229
|
+
name: import_joi102.default.string().required()
|
|
24230
|
+
})
|
|
24231
|
+
).optional().default([])
|
|
24232
|
+
}).required(),
|
|
24233
|
+
unitIds: import_joi102.default.array().items(import_joi102.default.string().hex().length(24)).optional()
|
|
24234
|
+
});
|
|
24235
|
+
function useStockMovementController() {
|
|
24236
|
+
const repo = useStockMovementRepo();
|
|
24237
|
+
const service = useStockMovementService();
|
|
24238
|
+
async function stockIn(req, res, next) {
|
|
24131
24239
|
try {
|
|
24132
|
-
|
|
24133
|
-
|
|
24134
|
-
|
|
24135
|
-
|
|
24136
|
-
|
|
24137
|
-
|
|
24240
|
+
const { error } = stockInSchema.validate(req.body);
|
|
24241
|
+
if (error) {
|
|
24242
|
+
next(new import_utils124.BadRequestError(error.message));
|
|
24243
|
+
return;
|
|
24244
|
+
}
|
|
24245
|
+
const { units, ...movement } = req.body;
|
|
24246
|
+
const movementId = await service.stockIn(movement, units);
|
|
24247
|
+
res.status(201).json({
|
|
24248
|
+
message: "Stock in recorded successfully.",
|
|
24249
|
+
movementId
|
|
24250
|
+
});
|
|
24138
24251
|
} catch (error) {
|
|
24139
|
-
|
|
24252
|
+
next(error);
|
|
24140
24253
|
}
|
|
24141
24254
|
}
|
|
24142
|
-
async function
|
|
24255
|
+
async function stockOut(req, res, next) {
|
|
24143
24256
|
try {
|
|
24144
|
-
|
|
24145
|
-
|
|
24146
|
-
|
|
24147
|
-
|
|
24257
|
+
const { error } = stockOutSchema.validate(req.body);
|
|
24258
|
+
if (error) {
|
|
24259
|
+
next(new import_utils124.BadRequestError(error.message));
|
|
24260
|
+
return;
|
|
24261
|
+
}
|
|
24262
|
+
const { unitIds, ...movement } = req.body;
|
|
24263
|
+
const movementId = await service.stockOut(movement, unitIds);
|
|
24264
|
+
res.status(201).json({
|
|
24265
|
+
message: "Stock out recorded successfully.",
|
|
24266
|
+
movementId
|
|
24267
|
+
});
|
|
24148
24268
|
} catch (error) {
|
|
24149
|
-
|
|
24150
|
-
throw new import_utils124.InternalServerError("Failed to create stock movement.");
|
|
24269
|
+
next(error);
|
|
24151
24270
|
}
|
|
24152
24271
|
}
|
|
24153
|
-
async function
|
|
24154
|
-
itemId,
|
|
24155
|
-
type = "",
|
|
24156
|
-
page = 1,
|
|
24157
|
-
limit = 10
|
|
24158
|
-
}) {
|
|
24159
|
-
page = page > 0 ? page - 1 : 0;
|
|
24160
|
-
const query = {
|
|
24161
|
-
itemId: new import_mongodb67.ObjectId(itemId)
|
|
24162
|
-
};
|
|
24163
|
-
if (type) {
|
|
24164
|
-
query.type = type;
|
|
24165
|
-
}
|
|
24166
|
-
const cacheKey = (0, import_utils124.makeCacheKey)(namespace_collection, {
|
|
24167
|
-
itemId,
|
|
24168
|
-
type,
|
|
24169
|
-
page,
|
|
24170
|
-
limit,
|
|
24171
|
-
tag: "byItemId"
|
|
24172
|
-
});
|
|
24272
|
+
async function transfer(req, res, next) {
|
|
24173
24273
|
try {
|
|
24174
|
-
const
|
|
24175
|
-
if (
|
|
24176
|
-
|
|
24177
|
-
|
|
24178
|
-
|
|
24179
|
-
|
|
24180
|
-
|
|
24181
|
-
|
|
24182
|
-
|
|
24183
|
-
|
|
24184
|
-
|
|
24185
|
-
repo.setCache(cacheKey, data, 600);
|
|
24186
|
-
return data;
|
|
24274
|
+
const { error } = transferSchema.validate(req.body);
|
|
24275
|
+
if (error) {
|
|
24276
|
+
next(new import_utils124.BadRequestError(error.message));
|
|
24277
|
+
return;
|
|
24278
|
+
}
|
|
24279
|
+
const { unitIds, ...movement } = req.body;
|
|
24280
|
+
const movementId = await service.transfer(movement, unitIds);
|
|
24281
|
+
res.status(201).json({
|
|
24282
|
+
message: "Transfer recorded successfully.",
|
|
24283
|
+
movementId
|
|
24284
|
+
});
|
|
24187
24285
|
} catch (error) {
|
|
24188
|
-
|
|
24189
|
-
throw error;
|
|
24286
|
+
next(error);
|
|
24190
24287
|
}
|
|
24191
24288
|
}
|
|
24192
|
-
async function
|
|
24193
|
-
const cacheKey = (0, import_utils124.makeCacheKey)(namespace_collection, {
|
|
24194
|
-
id,
|
|
24195
|
-
tag: "by-id"
|
|
24196
|
-
});
|
|
24289
|
+
async function adjustment(req, res, next) {
|
|
24197
24290
|
try {
|
|
24198
|
-
const
|
|
24199
|
-
if (
|
|
24200
|
-
|
|
24201
|
-
|
|
24202
|
-
|
|
24291
|
+
const { error } = adjustmentSchema.validate(req.body);
|
|
24292
|
+
if (error) {
|
|
24293
|
+
next(new import_utils124.BadRequestError(error.message));
|
|
24294
|
+
return;
|
|
24295
|
+
}
|
|
24296
|
+
const movementId = await service.adjustment(req.body);
|
|
24297
|
+
res.status(201).json({
|
|
24298
|
+
message: "Adjustment recorded successfully.",
|
|
24299
|
+
movementId
|
|
24203
24300
|
});
|
|
24204
|
-
|
|
24205
|
-
|
|
24301
|
+
} catch (error) {
|
|
24302
|
+
next(error);
|
|
24303
|
+
}
|
|
24304
|
+
}
|
|
24305
|
+
async function getByItemId(req, res, next) {
|
|
24306
|
+
const { error } = querySchema.validate(req.query);
|
|
24307
|
+
if (error) {
|
|
24308
|
+
next(new import_utils124.BadRequestError(error.message));
|
|
24309
|
+
return;
|
|
24310
|
+
}
|
|
24311
|
+
const itemId = req.query.itemId;
|
|
24312
|
+
const type = req.query.type ?? "";
|
|
24313
|
+
const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
|
|
24314
|
+
const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
|
|
24315
|
+
try {
|
|
24316
|
+
const results = await repo.getByItemId({ itemId, type, page, limit });
|
|
24317
|
+
res.json(results);
|
|
24318
|
+
} catch (error2) {
|
|
24319
|
+
next(error2);
|
|
24320
|
+
}
|
|
24321
|
+
}
|
|
24322
|
+
async function getById(req, res, next) {
|
|
24323
|
+
const { error } = idParamSchema2.validate(req.params);
|
|
24324
|
+
if (error) {
|
|
24325
|
+
next(new import_utils124.BadRequestError(error.message));
|
|
24326
|
+
return;
|
|
24327
|
+
}
|
|
24328
|
+
try {
|
|
24329
|
+
const movement = await repo.getById(req.params.id);
|
|
24330
|
+
res.json(movement);
|
|
24331
|
+
} catch (error2) {
|
|
24332
|
+
next(error2);
|
|
24333
|
+
}
|
|
24334
|
+
}
|
|
24335
|
+
async function conversion(req, res, next) {
|
|
24336
|
+
try {
|
|
24337
|
+
const { error } = conversionSchema.validate(req.body);
|
|
24338
|
+
if (error) {
|
|
24339
|
+
next(new import_utils124.BadRequestError(error.message));
|
|
24340
|
+
return;
|
|
24206
24341
|
}
|
|
24207
|
-
|
|
24208
|
-
|
|
24342
|
+
const { quantity, newItem, unitIds } = req.body;
|
|
24343
|
+
const result = await service.conversion(newItem, quantity, unitIds);
|
|
24344
|
+
res.status(201).json({
|
|
24345
|
+
message: "Conversion recorded successfully.",
|
|
24346
|
+
movementId: result.movementId,
|
|
24347
|
+
newItemId: result.newItemId
|
|
24348
|
+
});
|
|
24209
24349
|
} catch (error) {
|
|
24210
|
-
|
|
24211
|
-
throw error;
|
|
24212
|
-
throw new import_utils124.InternalServerError("Failed to get stock movement.");
|
|
24350
|
+
next(error);
|
|
24213
24351
|
}
|
|
24214
24352
|
}
|
|
24215
24353
|
return {
|
|
24216
|
-
|
|
24217
|
-
|
|
24354
|
+
stockIn,
|
|
24355
|
+
stockOut,
|
|
24356
|
+
transfer,
|
|
24357
|
+
adjustment,
|
|
24358
|
+
conversion,
|
|
24218
24359
|
getByItemId,
|
|
24219
24360
|
getById
|
|
24220
24361
|
};
|
|
24221
24362
|
}
|
|
24222
24363
|
|
|
24223
|
-
// src/resources/asset-item-
|
|
24364
|
+
// src/resources/asset-item-unit/asset.unit.controller.ts
|
|
24365
|
+
var import_joi103 = __toESM(require("joi"));
|
|
24224
24366
|
var import_utils125 = require("@goweekdays/utils");
|
|
24225
|
-
var
|
|
24226
|
-
|
|
24227
|
-
|
|
24228
|
-
|
|
24229
|
-
|
|
24230
|
-
|
|
24231
|
-
|
|
24232
|
-
|
|
24233
|
-
|
|
24234
|
-
|
|
24367
|
+
var querySchema2 = import_joi103.default.object({
|
|
24368
|
+
itemId: import_joi103.default.string().hex().length(24).required(),
|
|
24369
|
+
status: import_joi103.default.string().valid(...assetUnitStatuses).optional().allow("", null),
|
|
24370
|
+
page: import_joi103.default.number().min(1).optional().allow("", null),
|
|
24371
|
+
limit: import_joi103.default.number().min(1).optional().allow("", null)
|
|
24372
|
+
});
|
|
24373
|
+
var idParamSchema3 = import_joi103.default.object({
|
|
24374
|
+
id: import_joi103.default.string().hex().length(24).required()
|
|
24375
|
+
});
|
|
24376
|
+
function useAssetUnitController() {
|
|
24377
|
+
const repo = useAssetUnitRepo();
|
|
24378
|
+
async function add(req, res, next) {
|
|
24235
24379
|
try {
|
|
24236
|
-
|
|
24237
|
-
|
|
24238
|
-
|
|
24239
|
-
|
|
24240
|
-
for (const unit of units) {
|
|
24241
|
-
await assetUnitRepo.add(
|
|
24242
|
-
{
|
|
24243
|
-
itemId: value.itemId,
|
|
24244
|
-
serialNumber: unit.serialNumber,
|
|
24245
|
-
plateNumber: unit.plateNumber,
|
|
24246
|
-
status: "available",
|
|
24247
|
-
locationId: value.toLocationId
|
|
24248
|
-
},
|
|
24249
|
-
session
|
|
24250
|
-
);
|
|
24251
|
-
}
|
|
24380
|
+
const { error } = schemaAssetUnit.validate(req.body);
|
|
24381
|
+
if (error) {
|
|
24382
|
+
next(new import_utils125.BadRequestError(error.message));
|
|
24383
|
+
return;
|
|
24252
24384
|
}
|
|
24253
|
-
await
|
|
24254
|
-
|
|
24255
|
-
|
|
24256
|
-
|
|
24257
|
-
);
|
|
24258
|
-
await session.commitTransaction();
|
|
24259
|
-
return movementId;
|
|
24385
|
+
const unitId = await repo.add(req.body);
|
|
24386
|
+
res.status(201).json({
|
|
24387
|
+
message: "Asset unit created successfully.",
|
|
24388
|
+
unitId
|
|
24389
|
+
});
|
|
24260
24390
|
} catch (error) {
|
|
24261
|
-
|
|
24262
|
-
throw error;
|
|
24263
|
-
} finally {
|
|
24264
|
-
await session.endSession();
|
|
24391
|
+
next(error);
|
|
24265
24392
|
}
|
|
24266
24393
|
}
|
|
24267
|
-
async function
|
|
24268
|
-
const
|
|
24269
|
-
if (
|
|
24270
|
-
|
|
24394
|
+
async function getByItemId(req, res, next) {
|
|
24395
|
+
const { error } = querySchema2.validate(req.query);
|
|
24396
|
+
if (error) {
|
|
24397
|
+
next(new import_utils125.BadRequestError(error.message));
|
|
24398
|
+
return;
|
|
24271
24399
|
}
|
|
24272
|
-
const
|
|
24273
|
-
|
|
24274
|
-
|
|
24400
|
+
const itemId = req.query.itemId;
|
|
24401
|
+
const status2 = req.query.status ?? "";
|
|
24402
|
+
const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
|
|
24403
|
+
const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
|
|
24275
24404
|
try {
|
|
24276
|
-
|
|
24277
|
-
|
|
24278
|
-
|
|
24279
|
-
|
|
24280
|
-
for (const unitId of unitIds) {
|
|
24281
|
-
await assetUnitRepo.updateById(
|
|
24282
|
-
unitId,
|
|
24283
|
-
{ status: "assigned", assignedTo: value.reference?.id },
|
|
24284
|
-
session
|
|
24285
|
-
);
|
|
24286
|
-
}
|
|
24287
|
-
}
|
|
24288
|
-
await assetItemRepo.incrementQuantity(
|
|
24289
|
-
String(value.itemId),
|
|
24290
|
-
-value.quantity,
|
|
24291
|
-
session
|
|
24292
|
-
);
|
|
24293
|
-
await session.commitTransaction();
|
|
24294
|
-
return movementId;
|
|
24295
|
-
} catch (error) {
|
|
24296
|
-
await session.abortTransaction();
|
|
24297
|
-
throw error;
|
|
24298
|
-
} finally {
|
|
24299
|
-
await session.endSession();
|
|
24405
|
+
const results = await repo.getByItemId({ itemId, status: status2, page, limit });
|
|
24406
|
+
res.json(results);
|
|
24407
|
+
} catch (error2) {
|
|
24408
|
+
next(error2);
|
|
24300
24409
|
}
|
|
24301
24410
|
}
|
|
24302
|
-
async function
|
|
24303
|
-
|
|
24304
|
-
|
|
24305
|
-
|
|
24306
|
-
|
|
24411
|
+
async function getById(req, res, next) {
|
|
24412
|
+
const { error } = idParamSchema3.validate(req.params);
|
|
24413
|
+
if (error) {
|
|
24414
|
+
next(new import_utils125.BadRequestError(error.message));
|
|
24415
|
+
return;
|
|
24307
24416
|
}
|
|
24308
|
-
const item = await assetItemRepo.getById(String(value.itemId));
|
|
24309
|
-
const session = import_utils126.useAtlas.getClient()?.startSession();
|
|
24310
|
-
if (!session)
|
|
24311
|
-
throw new import_utils125.BadRequestError("Failed to start session.");
|
|
24312
24417
|
try {
|
|
24313
|
-
|
|
24314
|
-
|
|
24315
|
-
|
|
24316
|
-
|
|
24317
|
-
|
|
24318
|
-
|
|
24319
|
-
|
|
24320
|
-
|
|
24321
|
-
|
|
24322
|
-
|
|
24323
|
-
|
|
24324
|
-
|
|
24325
|
-
|
|
24326
|
-
|
|
24418
|
+
const unit = await repo.getById(req.params.id);
|
|
24419
|
+
res.json(unit);
|
|
24420
|
+
} catch (error2) {
|
|
24421
|
+
next(error2);
|
|
24422
|
+
}
|
|
24423
|
+
}
|
|
24424
|
+
async function updateById(req, res, next) {
|
|
24425
|
+
const { error: paramError } = idParamSchema3.validate(req.params);
|
|
24426
|
+
if (paramError) {
|
|
24427
|
+
next(new import_utils125.BadRequestError(paramError.message));
|
|
24428
|
+
return;
|
|
24429
|
+
}
|
|
24430
|
+
const { error: bodyError } = schemaAssetUnitUpdate.validate(req.body);
|
|
24431
|
+
if (bodyError) {
|
|
24432
|
+
next(new import_utils125.BadRequestError(bodyError.message));
|
|
24433
|
+
return;
|
|
24434
|
+
}
|
|
24435
|
+
try {
|
|
24436
|
+
const updatedUnit = await repo.updateById(req.params.id, req.body);
|
|
24437
|
+
res.json({
|
|
24438
|
+
message: "Asset unit updated successfully.",
|
|
24439
|
+
unit: updatedUnit
|
|
24440
|
+
});
|
|
24327
24441
|
} catch (error) {
|
|
24328
|
-
|
|
24329
|
-
throw error;
|
|
24330
|
-
} finally {
|
|
24331
|
-
await session.endSession();
|
|
24442
|
+
next(error);
|
|
24332
24443
|
}
|
|
24333
24444
|
}
|
|
24334
|
-
|
|
24335
|
-
|
|
24336
|
-
|
|
24445
|
+
return {
|
|
24446
|
+
add,
|
|
24447
|
+
getByItemId,
|
|
24448
|
+
getById,
|
|
24449
|
+
updateById
|
|
24450
|
+
};
|
|
24451
|
+
}
|
|
24452
|
+
|
|
24453
|
+
// src/resources/asset-item/asset.item.service.ts
|
|
24454
|
+
function normalizeTagName(name) {
|
|
24455
|
+
return name.trim().toLowerCase().replace(/\s+/g, "-");
|
|
24456
|
+
}
|
|
24457
|
+
function useAssetItemService() {
|
|
24458
|
+
const assetItemRepo = useAssetItemRepo();
|
|
24459
|
+
const tagRepo = useTagRepo();
|
|
24460
|
+
const categoryRepo = useCategoryRepo();
|
|
24461
|
+
const stockMovementRepo = useStockMovementRepo();
|
|
24462
|
+
const assetUnitRepo = useAssetUnitRepo();
|
|
24463
|
+
async function resolveTags(tagNames, orgId, categoryPath, session) {
|
|
24464
|
+
const resolvedTags = [];
|
|
24465
|
+
for (const tag of tagNames) {
|
|
24466
|
+
const normalizedName = normalizeTagName(tag.name);
|
|
24467
|
+
const existing = await tagRepo.findByNormalizedNameAndOrg(
|
|
24468
|
+
normalizedName,
|
|
24469
|
+
orgId
|
|
24470
|
+
);
|
|
24471
|
+
if (existing && existing._id) {
|
|
24472
|
+
await tagRepo.incrementUsageCount(existing._id, 1, session);
|
|
24473
|
+
resolvedTags.push({
|
|
24474
|
+
id: String(existing._id),
|
|
24475
|
+
name: existing.name
|
|
24476
|
+
});
|
|
24477
|
+
} else {
|
|
24478
|
+
const tagData = {
|
|
24479
|
+
name: tag.name.trim(),
|
|
24480
|
+
normalizedName,
|
|
24481
|
+
type: "private",
|
|
24482
|
+
orgId,
|
|
24483
|
+
categoryPath,
|
|
24484
|
+
status: "active",
|
|
24485
|
+
usageCount: 1
|
|
24486
|
+
};
|
|
24487
|
+
const tagId = await tagRepo.add(tagData, session);
|
|
24488
|
+
resolvedTags.push({
|
|
24489
|
+
id: String(tagId),
|
|
24490
|
+
name: tag.name.trim()
|
|
24491
|
+
});
|
|
24492
|
+
}
|
|
24337
24493
|
}
|
|
24494
|
+
return resolvedTags;
|
|
24495
|
+
}
|
|
24496
|
+
async function add(value) {
|
|
24338
24497
|
const session = import_utils126.useAtlas.getClient()?.startSession();
|
|
24339
|
-
if (!session)
|
|
24340
|
-
throw new
|
|
24498
|
+
if (!session) {
|
|
24499
|
+
throw new import_utils126.InternalServerError(
|
|
24500
|
+
"Unable to start session for asset item service."
|
|
24501
|
+
);
|
|
24502
|
+
}
|
|
24341
24503
|
try {
|
|
24342
|
-
session.startTransaction();
|
|
24343
|
-
|
|
24344
|
-
|
|
24345
|
-
|
|
24346
|
-
|
|
24347
|
-
value.
|
|
24348
|
-
|
|
24504
|
+
await session.startTransaction();
|
|
24505
|
+
const department = await categoryRepo.getById(value.departmentId);
|
|
24506
|
+
value.departmentName = department.displayName;
|
|
24507
|
+
if (value.categoryId) {
|
|
24508
|
+
const category = await categoryRepo.getById(value.categoryId);
|
|
24509
|
+
value.categoryName = category.displayName;
|
|
24510
|
+
}
|
|
24511
|
+
if (value.subcategoryId) {
|
|
24512
|
+
const subcategory = await categoryRepo.getById(value.subcategoryId);
|
|
24513
|
+
value.subcategoryName = subcategory.displayName;
|
|
24514
|
+
}
|
|
24515
|
+
const categoryPath = buildCategoryPath(
|
|
24516
|
+
value.departmentName,
|
|
24517
|
+
value.categoryName ?? "",
|
|
24518
|
+
value.subcategoryName ?? ""
|
|
24349
24519
|
);
|
|
24520
|
+
value.categoryPath = categoryPath;
|
|
24521
|
+
const resolvedTags = value.tags.length ? await resolveTags(
|
|
24522
|
+
value.tags,
|
|
24523
|
+
value.orgId,
|
|
24524
|
+
value.categoryPath,
|
|
24525
|
+
session
|
|
24526
|
+
) : [];
|
|
24527
|
+
const assetItem = {
|
|
24528
|
+
...value,
|
|
24529
|
+
tags: resolvedTags
|
|
24530
|
+
};
|
|
24531
|
+
const assetItemId = await assetItemRepo.add(assetItem, session);
|
|
24350
24532
|
await session.commitTransaction();
|
|
24351
|
-
return
|
|
24533
|
+
return assetItemId;
|
|
24352
24534
|
} catch (error) {
|
|
24353
24535
|
await session.abortTransaction();
|
|
24354
|
-
|
|
24536
|
+
if (error instanceof import_utils126.AppError)
|
|
24537
|
+
throw error;
|
|
24538
|
+
throw new import_utils126.InternalServerError("Failed to create asset item.");
|
|
24355
24539
|
} finally {
|
|
24356
|
-
|
|
24540
|
+
session.endSession();
|
|
24357
24541
|
}
|
|
24358
24542
|
}
|
|
24359
|
-
async function
|
|
24360
|
-
|
|
24361
|
-
|
|
24362
|
-
|
|
24543
|
+
async function makePublic(id, value) {
|
|
24544
|
+
try {
|
|
24545
|
+
await assetItemRepo.updateById(id, {
|
|
24546
|
+
isPublic: value,
|
|
24547
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
24548
|
+
});
|
|
24549
|
+
return "Asset item visibility updated successfully.";
|
|
24550
|
+
} catch (error) {
|
|
24551
|
+
if (error instanceof import_utils126.AppError)
|
|
24552
|
+
throw error;
|
|
24553
|
+
throw new import_utils126.InternalServerError("Failed to update asset item visibility.");
|
|
24363
24554
|
}
|
|
24364
|
-
|
|
24365
|
-
|
|
24555
|
+
}
|
|
24556
|
+
async function deleteById(id) {
|
|
24557
|
+
const [movementCount, unitCount] = await Promise.all([
|
|
24558
|
+
stockMovementRepo.countByItemId(id),
|
|
24559
|
+
assetUnitRepo.countByItemId(id)
|
|
24560
|
+
]);
|
|
24561
|
+
if (movementCount > 0 || unitCount > 0) {
|
|
24562
|
+
throw new import_utils126.BadRequestError(
|
|
24563
|
+
"Cannot delete asset item because it has associated movement or unit records."
|
|
24564
|
+
);
|
|
24366
24565
|
}
|
|
24367
|
-
const session = import_utils126.useAtlas.getClient()?.startSession();
|
|
24368
|
-
if (!session)
|
|
24369
|
-
throw new import_utils125.BadRequestError("Failed to start session.");
|
|
24370
24566
|
try {
|
|
24371
|
-
|
|
24372
|
-
|
|
24373
|
-
const movementData = {
|
|
24374
|
-
itemId: newItem.itemRefId,
|
|
24375
|
-
type: "conversion",
|
|
24376
|
-
quantity,
|
|
24377
|
-
fromItemId: String(newItem.itemRefId),
|
|
24378
|
-
toItemId: String(newItemId),
|
|
24379
|
-
reference: { type: "conversion", id: String(newItemId) }
|
|
24380
|
-
};
|
|
24381
|
-
const movementId = await movementRepo.add(movementData, session);
|
|
24382
|
-
await assetItemRepo.incrementQuantity(
|
|
24383
|
-
String(newItem.itemRefId),
|
|
24384
|
-
-quantity,
|
|
24385
|
-
session
|
|
24386
|
-
);
|
|
24387
|
-
await assetItemRepo.incrementQuantity(
|
|
24388
|
-
String(newItemId),
|
|
24389
|
-
quantity,
|
|
24390
|
-
session
|
|
24391
|
-
);
|
|
24392
|
-
if (sourceItem.trackingType === "individual" && unitIds && unitIds.length > 0) {
|
|
24393
|
-
for (const unitId of unitIds) {
|
|
24394
|
-
await assetUnitRepo.updateById(
|
|
24395
|
-
unitId,
|
|
24396
|
-
{ itemId: String(newItemId) },
|
|
24397
|
-
session
|
|
24398
|
-
);
|
|
24399
|
-
}
|
|
24400
|
-
}
|
|
24401
|
-
await session.commitTransaction();
|
|
24402
|
-
return { movementId, newItemId };
|
|
24567
|
+
await assetItemRepo.deleteById(id);
|
|
24568
|
+
return "Asset item deleted successfully.";
|
|
24403
24569
|
} catch (error) {
|
|
24404
|
-
|
|
24405
|
-
|
|
24406
|
-
|
|
24407
|
-
await session.endSession();
|
|
24570
|
+
if (error instanceof import_utils126.AppError)
|
|
24571
|
+
throw error;
|
|
24572
|
+
throw new import_utils126.InternalServerError("Failed to delete asset item.");
|
|
24408
24573
|
}
|
|
24409
24574
|
}
|
|
24410
24575
|
return {
|
|
24411
|
-
|
|
24412
|
-
|
|
24413
|
-
|
|
24414
|
-
adjustment,
|
|
24415
|
-
conversion
|
|
24576
|
+
add,
|
|
24577
|
+
makePublic,
|
|
24578
|
+
deleteById
|
|
24416
24579
|
};
|
|
24417
24580
|
}
|
|
24418
24581
|
|
|
24419
|
-
// src/resources/asset-item
|
|
24582
|
+
// src/resources/asset-item/asset.item.controller.ts
|
|
24420
24583
|
var import_joi104 = __toESM(require("joi"));
|
|
24421
24584
|
var import_utils127 = require("@goweekdays/utils");
|
|
24422
|
-
var
|
|
24423
|
-
itemId: import_joi104.default.string().hex().length(24).required(),
|
|
24424
|
-
type: import_joi104.default.string().valid(...stockMovementTypes).optional().allow("", null),
|
|
24585
|
+
var paginationSchema3 = import_joi104.default.object({
|
|
24425
24586
|
page: import_joi104.default.number().min(1).optional().allow("", null),
|
|
24426
|
-
limit: import_joi104.default.number().min(1).optional().allow("", null)
|
|
24587
|
+
limit: import_joi104.default.number().min(1).optional().allow("", null),
|
|
24588
|
+
search: import_joi104.default.string().optional().allow("", null),
|
|
24589
|
+
status: import_joi104.default.string().valid(...assetItemStatuses).optional().allow("", null),
|
|
24590
|
+
assetCategory: import_joi104.default.string().valid(...assetItemCategories).optional().allow("", null),
|
|
24591
|
+
trackingType: import_joi104.default.string().valid(...assetItemTrackingTypes).optional().allow("", null),
|
|
24592
|
+
purpose: import_joi104.default.string().valid(...assetItemPurposes).optional().allow("", null),
|
|
24593
|
+
departmentId: import_joi104.default.string().optional().allow("", null),
|
|
24594
|
+
categoryId: import_joi104.default.string().optional().allow("", null),
|
|
24595
|
+
subcategoryId: import_joi104.default.string().optional().allow("", null),
|
|
24596
|
+
brand: import_joi104.default.string().optional().allow("", null),
|
|
24597
|
+
tags: import_joi104.default.string().optional().allow("", null),
|
|
24598
|
+
public: import_joi104.default.boolean().optional().allow("", null)
|
|
24427
24599
|
});
|
|
24428
24600
|
var idParamSchema4 = import_joi104.default.object({
|
|
24429
24601
|
id: import_joi104.default.string().hex().length(24).required()
|
|
24430
24602
|
});
|
|
24431
|
-
|
|
24432
|
-
|
|
24433
|
-
|
|
24434
|
-
|
|
24435
|
-
totalCost: import_joi104.default.number().min(0).optional().allow(null),
|
|
24436
|
-
reference: import_joi104.default.object({
|
|
24437
|
-
type: import_joi104.default.string().valid("purchase", "sale", "transfer", "manual", "conversion").required(),
|
|
24438
|
-
id: import_joi104.default.string().optional().allow("", null)
|
|
24439
|
-
}).optional().allow(null),
|
|
24440
|
-
toLocationId: import_joi104.default.string().optional().allow("", null),
|
|
24441
|
-
units: import_joi104.default.array().items(
|
|
24442
|
-
import_joi104.default.object({
|
|
24443
|
-
serialNumber: import_joi104.default.string().optional().allow("", null),
|
|
24444
|
-
plateNumber: import_joi104.default.string().optional().allow("", null)
|
|
24445
|
-
})
|
|
24446
|
-
).optional()
|
|
24447
|
-
});
|
|
24448
|
-
var stockOutSchema = import_joi104.default.object({
|
|
24449
|
-
itemId: import_joi104.default.string().hex().length(24).required(),
|
|
24450
|
-
quantity: import_joi104.default.number().positive().required(),
|
|
24451
|
-
unitCost: import_joi104.default.number().min(0).optional().allow(null),
|
|
24452
|
-
totalCost: import_joi104.default.number().min(0).optional().allow(null),
|
|
24453
|
-
reference: import_joi104.default.object({
|
|
24454
|
-
type: import_joi104.default.string().valid("purchase", "sale", "transfer", "manual", "conversion").required(),
|
|
24455
|
-
id: import_joi104.default.string().optional().allow("", null)
|
|
24456
|
-
}).optional().allow(null),
|
|
24457
|
-
fromLocationId: import_joi104.default.string().optional().allow("", null),
|
|
24458
|
-
unitIds: import_joi104.default.array().items(import_joi104.default.string().hex().length(24)).optional()
|
|
24459
|
-
});
|
|
24460
|
-
var transferSchema = import_joi104.default.object({
|
|
24461
|
-
itemId: import_joi104.default.string().hex().length(24).required(),
|
|
24462
|
-
quantity: import_joi104.default.number().positive().required(),
|
|
24463
|
-
fromLocationId: import_joi104.default.string().required(),
|
|
24464
|
-
toLocationId: import_joi104.default.string().required(),
|
|
24465
|
-
reference: import_joi104.default.object({
|
|
24466
|
-
type: import_joi104.default.string().valid("purchase", "sale", "transfer", "manual", "conversion").required(),
|
|
24467
|
-
id: import_joi104.default.string().optional().allow("", null)
|
|
24468
|
-
}).optional().allow(null),
|
|
24469
|
-
unitIds: import_joi104.default.array().items(import_joi104.default.string().hex().length(24)).optional()
|
|
24470
|
-
});
|
|
24471
|
-
var adjustmentSchema = import_joi104.default.object({
|
|
24472
|
-
itemId: import_joi104.default.string().hex().length(24).required(),
|
|
24473
|
-
quantity: import_joi104.default.number().required(),
|
|
24474
|
-
reason: import_joi104.default.string().required(),
|
|
24475
|
-
reference: import_joi104.default.object({
|
|
24476
|
-
type: import_joi104.default.string().valid("purchase", "sale", "transfer", "manual", "conversion").required(),
|
|
24477
|
-
id: import_joi104.default.string().optional().allow("", null)
|
|
24478
|
-
}).optional().allow(null)
|
|
24479
|
-
});
|
|
24480
|
-
var conversionSchema = import_joi104.default.object({
|
|
24481
|
-
quantity: import_joi104.default.number().positive().required(),
|
|
24482
|
-
newItem: import_joi104.default.object({
|
|
24483
|
-
name: import_joi104.default.string().required(),
|
|
24484
|
-
description: import_joi104.default.string().optional().allow("", null),
|
|
24485
|
-
assetCategory: import_joi104.default.string().valid(...assetItemCategories).required(),
|
|
24486
|
-
assetClass: import_joi104.default.string().valid(...assetItemClasses).required(),
|
|
24487
|
-
trackingType: import_joi104.default.string().valid(...assetItemTrackingTypes).required(),
|
|
24488
|
-
purpose: import_joi104.default.string().valid(...assetItemPurposes).required(),
|
|
24489
|
-
itemRefId: import_joi104.default.string().hex().length(24).required(),
|
|
24490
|
-
remarks: import_joi104.default.string().optional().allow("", null),
|
|
24491
|
-
departmentId: import_joi104.default.string().required(),
|
|
24492
|
-
departmentName: import_joi104.default.string().required(),
|
|
24493
|
-
categoryId: import_joi104.default.string().required(),
|
|
24494
|
-
categoryName: import_joi104.default.string().required(),
|
|
24495
|
-
subcategoryId: import_joi104.default.string().required(),
|
|
24496
|
-
subcategoryName: import_joi104.default.string().required(),
|
|
24497
|
-
categoryPath: import_joi104.default.string().required(),
|
|
24498
|
-
brand: import_joi104.default.string().optional().allow("", null),
|
|
24499
|
-
tags: import_joi104.default.array().items(
|
|
24500
|
-
import_joi104.default.object({
|
|
24501
|
-
id: import_joi104.default.string().required(),
|
|
24502
|
-
name: import_joi104.default.string().required()
|
|
24503
|
-
})
|
|
24504
|
-
).optional().default([])
|
|
24505
|
-
}).required(),
|
|
24506
|
-
unitIds: import_joi104.default.array().items(import_joi104.default.string().hex().length(24)).optional()
|
|
24507
|
-
});
|
|
24508
|
-
function useStockMovementController() {
|
|
24509
|
-
const repo = useStockMovementRepo();
|
|
24510
|
-
const service = useStockMovementService();
|
|
24511
|
-
async function stockIn(req, res, next) {
|
|
24603
|
+
function useAssetItemController() {
|
|
24604
|
+
const repo = useAssetItemRepo();
|
|
24605
|
+
const service = useAssetItemService();
|
|
24606
|
+
async function add(req, res, next) {
|
|
24512
24607
|
try {
|
|
24513
|
-
const { error } =
|
|
24608
|
+
const { error, value } = schemaAssetItemCreate.validate(req.body);
|
|
24514
24609
|
if (error) {
|
|
24515
24610
|
next(new import_utils127.BadRequestError(error.message));
|
|
24516
24611
|
return;
|
|
24517
24612
|
}
|
|
24518
|
-
const
|
|
24519
|
-
const movementId = await service.stockIn(movement, units);
|
|
24613
|
+
const assetItemId = await service.add(value);
|
|
24520
24614
|
res.status(201).json({
|
|
24521
|
-
message: "
|
|
24522
|
-
|
|
24615
|
+
message: "Asset item created successfully.",
|
|
24616
|
+
assetItemId
|
|
24523
24617
|
});
|
|
24524
24618
|
} catch (error) {
|
|
24525
24619
|
next(error);
|
|
24526
24620
|
}
|
|
24527
24621
|
}
|
|
24528
|
-
async function
|
|
24622
|
+
async function getAll(req, res, next) {
|
|
24623
|
+
const { error } = paginationSchema3.validate(req.query);
|
|
24624
|
+
if (error) {
|
|
24625
|
+
next(new import_utils127.BadRequestError(error.message));
|
|
24626
|
+
return;
|
|
24627
|
+
}
|
|
24628
|
+
const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
|
|
24629
|
+
const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
|
|
24630
|
+
const search = req.query.search ?? "";
|
|
24631
|
+
const status2 = req.query.status ?? "active";
|
|
24632
|
+
const assetCategory = req.query.assetCategory ?? "";
|
|
24633
|
+
const trackingType = req.query.trackingType ?? "";
|
|
24634
|
+
const purpose = req.query.purpose ?? "";
|
|
24635
|
+
const departmentId = req.query.departmentId ?? "";
|
|
24636
|
+
const categoryId = req.query.categoryId ?? "";
|
|
24637
|
+
const subcategoryId = req.query.subcategoryId ?? "";
|
|
24638
|
+
const brand = req.query.brand ?? "";
|
|
24639
|
+
const tagsParam = req.query.tags ?? "";
|
|
24640
|
+
const tags = tagsParam ? tagsParam.split(",").filter(Boolean) : [];
|
|
24641
|
+
const isPublic = req.query.public === "true";
|
|
24642
|
+
if (!isFinite(page)) {
|
|
24643
|
+
next(new import_utils127.BadRequestError("Invalid page number."));
|
|
24644
|
+
return;
|
|
24645
|
+
}
|
|
24646
|
+
if (!isFinite(limit)) {
|
|
24647
|
+
next(new import_utils127.BadRequestError("Invalid limit number."));
|
|
24648
|
+
return;
|
|
24649
|
+
}
|
|
24529
24650
|
try {
|
|
24530
|
-
const
|
|
24531
|
-
|
|
24532
|
-
|
|
24533
|
-
|
|
24534
|
-
|
|
24535
|
-
|
|
24536
|
-
|
|
24537
|
-
|
|
24538
|
-
|
|
24539
|
-
|
|
24651
|
+
const results = await repo.getAll({
|
|
24652
|
+
page,
|
|
24653
|
+
limit,
|
|
24654
|
+
search,
|
|
24655
|
+
status: status2,
|
|
24656
|
+
assetCategory,
|
|
24657
|
+
trackingType,
|
|
24658
|
+
purpose,
|
|
24659
|
+
departmentId,
|
|
24660
|
+
categoryId,
|
|
24661
|
+
subcategoryId,
|
|
24662
|
+
brand,
|
|
24663
|
+
tags,
|
|
24664
|
+
isPublic
|
|
24540
24665
|
});
|
|
24541
|
-
|
|
24542
|
-
|
|
24666
|
+
res.json(results);
|
|
24667
|
+
} catch (error2) {
|
|
24668
|
+
next(error2);
|
|
24543
24669
|
}
|
|
24544
24670
|
}
|
|
24545
|
-
async function
|
|
24671
|
+
async function getById(req, res, next) {
|
|
24672
|
+
const { error } = idParamSchema4.validate(req.params);
|
|
24673
|
+
if (error) {
|
|
24674
|
+
next(new import_utils127.BadRequestError(error.message));
|
|
24675
|
+
return;
|
|
24676
|
+
}
|
|
24546
24677
|
try {
|
|
24547
|
-
const
|
|
24548
|
-
|
|
24549
|
-
|
|
24550
|
-
|
|
24551
|
-
}
|
|
24552
|
-
const { unitIds, ...movement } = req.body;
|
|
24553
|
-
const movementId = await service.transfer(movement, unitIds);
|
|
24554
|
-
res.status(201).json({
|
|
24555
|
-
message: "Transfer recorded successfully.",
|
|
24556
|
-
movementId
|
|
24557
|
-
});
|
|
24558
|
-
} catch (error) {
|
|
24559
|
-
next(error);
|
|
24678
|
+
const assetItem = await repo.getById(req.params.id);
|
|
24679
|
+
res.json(assetItem);
|
|
24680
|
+
} catch (error2) {
|
|
24681
|
+
next(error2);
|
|
24560
24682
|
}
|
|
24561
24683
|
}
|
|
24562
|
-
async function
|
|
24684
|
+
async function updateById(req, res, next) {
|
|
24685
|
+
const { error: paramError } = import_joi104.default.object({
|
|
24686
|
+
id: import_joi104.default.string().hex().length(24).required(),
|
|
24687
|
+
orgId: import_joi104.default.string().hex().required()
|
|
24688
|
+
}).validate(req.params);
|
|
24689
|
+
if (paramError) {
|
|
24690
|
+
next(new import_utils127.BadRequestError(paramError.message));
|
|
24691
|
+
return;
|
|
24692
|
+
}
|
|
24693
|
+
const { error: bodyError } = schemaAssetItemUpdate.validate(req.body);
|
|
24694
|
+
if (bodyError) {
|
|
24695
|
+
next(new import_utils127.BadRequestError(bodyError.message));
|
|
24696
|
+
return;
|
|
24697
|
+
}
|
|
24563
24698
|
try {
|
|
24564
|
-
const
|
|
24565
|
-
|
|
24566
|
-
|
|
24567
|
-
|
|
24568
|
-
}
|
|
24569
|
-
const movementId = await service.adjustment(req.body);
|
|
24570
|
-
res.status(201).json({
|
|
24571
|
-
message: "Adjustment recorded successfully.",
|
|
24572
|
-
movementId
|
|
24699
|
+
const updatedAssetItem = await repo.updateById(req.params.id, req.body);
|
|
24700
|
+
res.json({
|
|
24701
|
+
message: "Asset item updated successfully.",
|
|
24702
|
+
assetItem: updatedAssetItem
|
|
24573
24703
|
});
|
|
24574
24704
|
} catch (error) {
|
|
24575
24705
|
next(error);
|
|
24576
24706
|
}
|
|
24577
24707
|
}
|
|
24578
|
-
async function
|
|
24579
|
-
const { error } =
|
|
24708
|
+
async function makePublic(req, res, next) {
|
|
24709
|
+
const { error, value } = import_joi104.default.object({
|
|
24710
|
+
orgId: import_joi104.default.string().hex().required(),
|
|
24711
|
+
id: import_joi104.default.string().hex().length(24).required(),
|
|
24712
|
+
isPublic: import_joi104.default.boolean().required()
|
|
24713
|
+
}).validate({ ...req.params, ...req.body });
|
|
24580
24714
|
if (error) {
|
|
24581
24715
|
next(new import_utils127.BadRequestError(error.message));
|
|
24582
24716
|
return;
|
|
24583
24717
|
}
|
|
24584
|
-
const itemId = req.query.itemId;
|
|
24585
|
-
const type = req.query.type ?? "";
|
|
24586
|
-
const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
|
|
24587
|
-
const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
|
|
24588
24718
|
try {
|
|
24589
|
-
const
|
|
24590
|
-
res.json(
|
|
24719
|
+
const message = await service.makePublic(value.id, value.isPublic);
|
|
24720
|
+
res.json({
|
|
24721
|
+
message
|
|
24722
|
+
});
|
|
24723
|
+
return;
|
|
24591
24724
|
} catch (error2) {
|
|
24592
|
-
|
|
24725
|
+
if (error2 instanceof import_utils127.AppError) {
|
|
24726
|
+
next(error2);
|
|
24727
|
+
return;
|
|
24728
|
+
}
|
|
24729
|
+
next(new import_utils127.InternalServerError("Failed to update asset item visibility."));
|
|
24593
24730
|
}
|
|
24594
24731
|
}
|
|
24595
|
-
async function
|
|
24596
|
-
const { error } =
|
|
24732
|
+
async function deleteById(req, res, next) {
|
|
24733
|
+
const { error } = import_joi104.default.object({
|
|
24734
|
+
id: import_joi104.default.string().hex().length(24).required(),
|
|
24735
|
+
orgId: import_joi104.default.string().hex().required()
|
|
24736
|
+
}).validate(req.params);
|
|
24597
24737
|
if (error) {
|
|
24598
24738
|
next(new import_utils127.BadRequestError(error.message));
|
|
24599
24739
|
return;
|
|
24600
24740
|
}
|
|
24601
24741
|
try {
|
|
24602
|
-
|
|
24603
|
-
res.json(
|
|
24742
|
+
await service.deleteById(req.params.id);
|
|
24743
|
+
res.json({
|
|
24744
|
+
message: "Asset item deleted successfully."
|
|
24745
|
+
});
|
|
24604
24746
|
} catch (error2) {
|
|
24605
24747
|
next(error2);
|
|
24606
24748
|
}
|
|
24607
24749
|
}
|
|
24608
|
-
async function conversion(req, res, next) {
|
|
24609
|
-
try {
|
|
24610
|
-
const { error } = conversionSchema.validate(req.body);
|
|
24611
|
-
if (error) {
|
|
24612
|
-
next(new import_utils127.BadRequestError(error.message));
|
|
24613
|
-
return;
|
|
24614
|
-
}
|
|
24615
|
-
const { quantity, newItem, unitIds } = req.body;
|
|
24616
|
-
const result = await service.conversion(newItem, quantity, unitIds);
|
|
24617
|
-
res.status(201).json({
|
|
24618
|
-
message: "Conversion recorded successfully.",
|
|
24619
|
-
movementId: result.movementId,
|
|
24620
|
-
newItemId: result.newItemId
|
|
24621
|
-
});
|
|
24622
|
-
} catch (error) {
|
|
24623
|
-
next(error);
|
|
24624
|
-
}
|
|
24625
|
-
}
|
|
24626
24750
|
return {
|
|
24627
|
-
|
|
24628
|
-
|
|
24629
|
-
|
|
24630
|
-
|
|
24631
|
-
|
|
24632
|
-
|
|
24633
|
-
getById
|
|
24751
|
+
add,
|
|
24752
|
+
getAll,
|
|
24753
|
+
getById,
|
|
24754
|
+
updateById,
|
|
24755
|
+
makePublic,
|
|
24756
|
+
deleteById
|
|
24634
24757
|
};
|
|
24635
24758
|
}
|
|
24636
24759
|
|