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