Refactor code structure for improved readability and maintainability
Test Suite / test (24.15.0) (push) Has been cancelled
Test Suite / test (24.15.0) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
export declare class AiCategorizeBulkDto {
|
||||
productIds?: number[];
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AiCategorizeBulkDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
class AiCategorizeBulkDto {
|
||||
}
|
||||
exports.AiCategorizeBulkDto = AiCategorizeBulkDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsArray)(),
|
||||
(0, class_validator_1.IsInt)({ each: true }),
|
||||
__metadata("design:type", Array)
|
||||
], AiCategorizeBulkDto.prototype, "productIds", void 0);
|
||||
//# sourceMappingURL=ai-categorize-bulk.dto.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"ai-categorize-bulk.dto.js","sourceRoot":"","sources":["../../../src/products/dto/ai-categorize-bulk.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA6D;AAE7D,MAAa,mBAAmB;CAK/B;AALD,kDAKC;AADC;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,yBAAO,GAAE;IACT,IAAA,uBAAK,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;;uDACA"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export declare class BulkUpdateProductsDto {
|
||||
ids: number[];
|
||||
categoryId?: number | null;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BulkUpdateProductsDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
class BulkUpdateProductsDto {
|
||||
}
|
||||
exports.BulkUpdateProductsDto = BulkUpdateProductsDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsArray)(),
|
||||
(0, class_validator_1.ArrayMinSize)(1),
|
||||
(0, class_validator_1.IsInt)({ each: true }),
|
||||
__metadata("design:type", Array)
|
||||
], BulkUpdateProductsDto.prototype, "ids", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
__metadata("design:type", Object)
|
||||
], BulkUpdateProductsDto.prototype, "categoryId", void 0);
|
||||
//# sourceMappingURL=bulk-update-products.dto.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"bulk-update-products.dto.js","sourceRoot":"","sources":["../../../src/products/dto/bulk-update-products.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAqF;AAErF,MAAa,qBAAqB;CASjC;AATD,sDASC;AALC;IAHC,IAAA,yBAAO,GAAE;IACT,IAAA,8BAAY,EAAC,CAAC,CAAC;IACf,IAAA,uBAAK,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;;kDACR;AAId;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;yDACgB"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export declare class CreateProductDto {
|
||||
name: string;
|
||||
categoryId?: number;
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CreateProductDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
class CreateProductDto {
|
||||
}
|
||||
exports.CreateProductDto = CreateProductDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsString)(),
|
||||
(0, class_validator_1.IsNotEmpty)(),
|
||||
(0, class_validator_1.MaxLength)(191),
|
||||
__metadata("design:type", String)
|
||||
], CreateProductDto.prototype, "name", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsInt)(),
|
||||
__metadata("design:type", Number)
|
||||
], CreateProductDto.prototype, "categoryId", void 0);
|
||||
//# sourceMappingURL=create-product.dto.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"create-product.dto.js","sourceRoot":"","sources":["../../../src/products/dto/create-product.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAqF;AAErF,MAAa,gBAAgB;CAS5B;AATD,4CASC;AALC;IAHC,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;IACZ,IAAA,2BAAS,EAAC,GAAG,CAAC;;8CACD;AAId;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,uBAAK,GAAE;;oDACY"}
|
||||
@@ -0,0 +1,4 @@
|
||||
export declare class MergeProductsDto {
|
||||
sourceProductId: number;
|
||||
targetProductId: number;
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.MergeProductsDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
class MergeProductsDto {
|
||||
}
|
||||
exports.MergeProductsDto = MergeProductsDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsInt)(),
|
||||
__metadata("design:type", Number)
|
||||
], MergeProductsDto.prototype, "sourceProductId", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsInt)(),
|
||||
__metadata("design:type", Number)
|
||||
], MergeProductsDto.prototype, "targetProductId", void 0);
|
||||
//# sourceMappingURL=merge-products.dto.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"merge-products.dto.js","sourceRoot":"","sources":["../../../src/products/dto/merge-products.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAwC;AAExC,MAAa,gBAAgB;CAM5B;AAND,4CAMC;AAJC;IADC,IAAA,uBAAK,GAAE;;yDACiB;AAGzB;IADC,IAAA,uBAAK,GAAE;;yDACiB"}
|
||||
@@ -0,0 +1,3 @@
|
||||
export declare class SetProductStatusDto {
|
||||
status: string;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SetProductStatusDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
class SetProductStatusDto {
|
||||
}
|
||||
exports.SetProductStatusDto = SetProductStatusDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsIn)(['active', 'rejected']),
|
||||
__metadata("design:type", String)
|
||||
], SetProductStatusDto.prototype, "status", void 0);
|
||||
//# sourceMappingURL=set-product-status.dto.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"set-product-status.dto.js","sourceRoot":"","sources":["../../../src/products/dto/set-product-status.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAuC;AAEvC,MAAa,mBAAmB;CAG/B;AAHD,kDAGC;AADC;IADC,IAAA,sBAAI,EAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;;mDACd"}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export declare class SetTagsDto {
|
||||
tags: string[];
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.SetTagsDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
class SetTagsDto {
|
||||
}
|
||||
exports.SetTagsDto = SetTagsDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsArray)(),
|
||||
(0, class_validator_1.IsString)({ each: true }),
|
||||
(0, class_validator_1.MaxLength)(100, { each: true }),
|
||||
__metadata("design:type", Array)
|
||||
], SetTagsDto.prototype, "tags", void 0);
|
||||
//# sourceMappingURL=set-tags.dto.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"set-tags.dto.js","sourceRoot":"","sources":["../../../src/products/dto/set-tags.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA+D;AAE/D,MAAa,UAAU;CAKtB;AALD,gCAKC;AADC;IAHC,IAAA,yBAAO,GAAE;IACT,IAAA,0BAAQ,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACxB,IAAA,2BAAS,EAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;;wCACf"}
|
||||
@@ -0,0 +1,3 @@
|
||||
export declare class UpdateCanonicalNameDto {
|
||||
canonicalName: string;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UpdateCanonicalNameDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
class UpdateCanonicalNameDto {
|
||||
}
|
||||
exports.UpdateCanonicalNameDto = UpdateCanonicalNameDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsString)(),
|
||||
(0, class_validator_1.IsNotEmpty)(),
|
||||
(0, class_validator_1.MaxLength)(191),
|
||||
__metadata("design:type", String)
|
||||
], UpdateCanonicalNameDto.prototype, "canonicalName", void 0);
|
||||
//# sourceMappingURL=update-canonical-name.dto.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"update-canonical-name.dto.js","sourceRoot":"","sources":["../../../src/products/dto/update-canonical-name.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAkE;AAElE,MAAa,sBAAsB;CAKlC;AALD,wDAKC;AADC;IAHC,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;IACZ,IAAA,2BAAS,EAAC,GAAG,CAAC;;6DACQ"}
|
||||
@@ -0,0 +1,7 @@
|
||||
export declare class UpdateProductDto {
|
||||
name?: string;
|
||||
canonicalName?: string;
|
||||
category?: string;
|
||||
subcategory?: string;
|
||||
categoryId?: number | null;
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UpdateProductDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
class UpdateProductDto {
|
||||
}
|
||||
exports.UpdateProductDto = UpdateProductDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsString)(),
|
||||
(0, class_validator_1.IsNotEmpty)(),
|
||||
(0, class_validator_1.MaxLength)(191),
|
||||
__metadata("design:type", String)
|
||||
], UpdateProductDto.prototype, "name", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsString)(),
|
||||
(0, class_validator_1.MaxLength)(191),
|
||||
__metadata("design:type", String)
|
||||
], UpdateProductDto.prototype, "canonicalName", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsString)(),
|
||||
(0, class_validator_1.MaxLength)(191),
|
||||
__metadata("design:type", String)
|
||||
], UpdateProductDto.prototype, "category", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsString)(),
|
||||
(0, class_validator_1.MaxLength)(191),
|
||||
__metadata("design:type", String)
|
||||
], UpdateProductDto.prototype, "subcategory", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
__metadata("design:type", Object)
|
||||
], UpdateProductDto.prototype, "categoryId", void 0);
|
||||
//# sourceMappingURL=update-product.dto.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"update-product.dto.js","sourceRoot":"","sources":["../../../src/products/dto/update-product.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAAwF;AAExF,MAAa,gBAAgB;CAyB5B;AAzBD,4CAyBC;AApBC;IAJC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,GAAE;IACZ,IAAA,2BAAS,EAAC,GAAG,CAAC;;8CACD;AAKd;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,GAAG,CAAC;;uDACQ;AAKvB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,GAAG,CAAC;;kDACG;AAKlB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,2BAAS,EAAC,GAAG,CAAC;;qDACM;AAIrB;IAFC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;;oDACgB"}
|
||||
@@ -0,0 +1,9 @@
|
||||
export declare class UpsertNutritionDto {
|
||||
calories?: number;
|
||||
protein?: number;
|
||||
fat?: number;
|
||||
carbohydrates?: number;
|
||||
salt?: number;
|
||||
sugar?: number;
|
||||
fiber?: number;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UpsertNutritionDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
class UpsertNutritionDto {
|
||||
}
|
||||
exports.UpsertNutritionDto = UpsertNutritionDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_validator_1.Min)(0),
|
||||
__metadata("design:type", Number)
|
||||
], UpsertNutritionDto.prototype, "calories", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_validator_1.Min)(0),
|
||||
__metadata("design:type", Number)
|
||||
], UpsertNutritionDto.prototype, "protein", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_validator_1.Min)(0),
|
||||
__metadata("design:type", Number)
|
||||
], UpsertNutritionDto.prototype, "fat", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_validator_1.Min)(0),
|
||||
__metadata("design:type", Number)
|
||||
], UpsertNutritionDto.prototype, "carbohydrates", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_validator_1.Min)(0),
|
||||
__metadata("design:type", Number)
|
||||
], UpsertNutritionDto.prototype, "salt", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_validator_1.Min)(0),
|
||||
__metadata("design:type", Number)
|
||||
], UpsertNutritionDto.prototype, "sugar", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsOptional)(),
|
||||
(0, class_validator_1.IsNumber)(),
|
||||
(0, class_validator_1.Min)(0),
|
||||
__metadata("design:type", Number)
|
||||
], UpsertNutritionDto.prototype, "fiber", void 0);
|
||||
//# sourceMappingURL=upsert-nutrition.dto.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"upsert-nutrition.dto.js","sourceRoot":"","sources":["../../../src/products/dto/upsert-nutrition.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA4D;AAE5D,MAAa,kBAAkB;CAmC9B;AAnCD,gDAmCC;AA/BC;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,CAAC;;oDACW;AAKlB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,CAAC;;mDACU;AAKjB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,CAAC;;+CACM;AAKb;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,CAAC;;yDACgB;AAKvB;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,CAAC;;gDACO;AAKd;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,CAAC;;iDACQ;AAKf;IAHC,IAAA,4BAAU,GAAE;IACZ,IAAA,0BAAQ,GAAE;IACV,IAAA,qBAAG,EAAC,CAAC,CAAC;;iDACQ"}
|
||||
+471
@@ -0,0 +1,471 @@
|
||||
import { CreateProductDto } from './dto/create-product.dto';
|
||||
import { UpdateProductDto } from './dto/update-product.dto';
|
||||
import { ProductsService } from './products.service';
|
||||
import { MergeProductsDto } from './dto/merge-products.dto';
|
||||
import { UpdateCanonicalNameDto } from './dto/update-canonical-name.dto';
|
||||
import { SetTagsDto } from './dto/set-tags.dto';
|
||||
import { UpsertNutritionDto } from './dto/upsert-nutrition.dto';
|
||||
import { BulkUpdateProductsDto } from './dto/bulk-update-products.dto';
|
||||
import { AiCategorizeBulkDto } from './dto/ai-categorize-bulk.dto';
|
||||
import { SetProductStatusDto } from './dto/set-product-status.dto';
|
||||
import { AiService } from '../ai/ai.service';
|
||||
import { CategoriesService } from '../categories/categories.service';
|
||||
export declare class ProductsController {
|
||||
private readonly productsService;
|
||||
private readonly aiService;
|
||||
private readonly categoriesService;
|
||||
constructor(productsService: ProductsService, aiService: AiService, categoriesService: CategoriesService);
|
||||
findAll(tag?: string): Promise<({
|
||||
nutrition: {
|
||||
calories: number | null;
|
||||
protein: number | null;
|
||||
fat: number | null;
|
||||
carbohydrates: number | null;
|
||||
salt: number | null;
|
||||
sugar: number | null;
|
||||
fiber: number | null;
|
||||
id: number;
|
||||
productId: number;
|
||||
} | null;
|
||||
tags: ({
|
||||
tag: {
|
||||
name: string;
|
||||
id: number;
|
||||
};
|
||||
} & {
|
||||
productId: number;
|
||||
tagId: number;
|
||||
})[];
|
||||
categoryRef: ({
|
||||
parent: ({
|
||||
parent: {
|
||||
name: string;
|
||||
id: number;
|
||||
parentId: number | null;
|
||||
} | null;
|
||||
} & {
|
||||
name: string;
|
||||
id: number;
|
||||
parentId: number | null;
|
||||
}) | null;
|
||||
} & {
|
||||
name: string;
|
||||
id: number;
|
||||
parentId: number | null;
|
||||
}) | null;
|
||||
} & {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
})[]>;
|
||||
findAllTags(): Promise<{
|
||||
name: string;
|
||||
id: number;
|
||||
}[]>;
|
||||
findDuplicates(): Promise<{
|
||||
normalizedName: string;
|
||||
count: number;
|
||||
products: {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}[];
|
||||
}[]>;
|
||||
previewMerge(sourceProductId: number, targetProductId: number): Promise<{
|
||||
source: {
|
||||
inventoryCount: number;
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
};
|
||||
target: {
|
||||
inventoryCount: number;
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
};
|
||||
outcome: {
|
||||
inventoryItemsToMove: number;
|
||||
sourceWillBeSoftDeleted: boolean;
|
||||
targetWillRemainActive: boolean;
|
||||
};
|
||||
}>;
|
||||
backfillCanonical(): Promise<{
|
||||
message: string;
|
||||
updatedCount: number;
|
||||
products: {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}[];
|
||||
}>;
|
||||
findPending(): Promise<({
|
||||
owner: {
|
||||
id: number;
|
||||
username: string;
|
||||
};
|
||||
categoryRef: ({
|
||||
parent: {
|
||||
name: string;
|
||||
id: number;
|
||||
parentId: number | null;
|
||||
} | null;
|
||||
} & {
|
||||
name: string;
|
||||
id: number;
|
||||
parentId: number | null;
|
||||
}) | null;
|
||||
} & {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
})[]>;
|
||||
aiCategorizeBulk(body: AiCategorizeBulkDto): Promise<{
|
||||
productId: number;
|
||||
productName: string;
|
||||
suggestion: object;
|
||||
}[]>;
|
||||
findDeleted(): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}[]>;
|
||||
findMine(req: {
|
||||
user: {
|
||||
id: number;
|
||||
};
|
||||
}): Promise<{
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
}[]>;
|
||||
findOne(id: number): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
createPrivate(body: CreateProductDto, req: {
|
||||
user: {
|
||||
id: number;
|
||||
};
|
||||
}): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
suggestCategory(id: number): Promise<import("../ai/ai.service").CategorySuggestion>;
|
||||
create(body: CreateProductDto, req: {
|
||||
user: {
|
||||
id: number;
|
||||
};
|
||||
}): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
createPending(body: CreateProductDto, req: {
|
||||
user: {
|
||||
id: number;
|
||||
};
|
||||
}): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
merge(body: MergeProductsDto): Promise<{
|
||||
message: string;
|
||||
sourceProductId: number;
|
||||
targetProductId: number;
|
||||
movedInventoryCount: number;
|
||||
softDeletedSource: {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
};
|
||||
}>;
|
||||
updateCanonicalName(id: number, body: UpdateCanonicalNameDto): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
setTags(id: number, body: SetTagsDto): Promise<({
|
||||
nutrition: {
|
||||
calories: number | null;
|
||||
protein: number | null;
|
||||
fat: number | null;
|
||||
carbohydrates: number | null;
|
||||
salt: number | null;
|
||||
sugar: number | null;
|
||||
fiber: number | null;
|
||||
id: number;
|
||||
productId: number;
|
||||
} | null;
|
||||
tags: ({
|
||||
tag: {
|
||||
name: string;
|
||||
id: number;
|
||||
};
|
||||
} & {
|
||||
productId: number;
|
||||
tagId: number;
|
||||
})[];
|
||||
} & {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}) | null>;
|
||||
upsertNutrition(id: number, body: UpsertNutritionDto): Promise<{
|
||||
calories: number | null;
|
||||
protein: number | null;
|
||||
fat: number | null;
|
||||
carbohydrates: number | null;
|
||||
salt: number | null;
|
||||
sugar: number | null;
|
||||
fiber: number | null;
|
||||
id: number;
|
||||
productId: number;
|
||||
}>;
|
||||
update(id: number, body: UpdateProductDto): Promise<{
|
||||
nutrition: {
|
||||
calories: number | null;
|
||||
protein: number | null;
|
||||
fat: number | null;
|
||||
carbohydrates: number | null;
|
||||
salt: number | null;
|
||||
sugar: number | null;
|
||||
fiber: number | null;
|
||||
id: number;
|
||||
productId: number;
|
||||
} | null;
|
||||
tags: ({
|
||||
tag: {
|
||||
name: string;
|
||||
id: number;
|
||||
};
|
||||
} & {
|
||||
productId: number;
|
||||
tagId: number;
|
||||
})[];
|
||||
} & {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
permanentDelete(id: number): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
remove(id: number): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
setStatus(id: number, body: SetProductStatusDto): import(".prisma/client").Prisma.Prisma__ProductClient<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
|
||||
restore(id: number): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
resetAll(): Promise<{
|
||||
ok: boolean;
|
||||
}>;
|
||||
bulkUpdate(body: BulkUpdateProductsDto): Promise<{
|
||||
updated: number;
|
||||
}>;
|
||||
}
|
||||
+328
@@ -0,0 +1,328 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ProductsController = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const throttler_1 = require("@nestjs/throttler");
|
||||
const public_decorator_1 = require("../auth/decorators/public.decorator");
|
||||
const create_product_dto_1 = require("./dto/create-product.dto");
|
||||
const update_product_dto_1 = require("./dto/update-product.dto");
|
||||
const products_service_1 = require("./products.service");
|
||||
const merge_products_dto_1 = require("./dto/merge-products.dto");
|
||||
const update_canonical_name_dto_1 = require("./dto/update-canonical-name.dto");
|
||||
const set_tags_dto_1 = require("./dto/set-tags.dto");
|
||||
const upsert_nutrition_dto_1 = require("./dto/upsert-nutrition.dto");
|
||||
const bulk_update_products_dto_1 = require("./dto/bulk-update-products.dto");
|
||||
const ai_categorize_bulk_dto_1 = require("./dto/ai-categorize-bulk.dto");
|
||||
const set_product_status_dto_1 = require("./dto/set-product-status.dto");
|
||||
const roles_decorator_1 = require("../auth/decorators/roles.decorator");
|
||||
const ai_service_1 = require("../ai/ai.service");
|
||||
const categories_service_1 = require("../categories/categories.service");
|
||||
const premium_or_admin_guard_1 = require("../auth/premium-or-admin.guard");
|
||||
let ProductsController = class ProductsController {
|
||||
constructor(productsService, aiService, categoriesService) {
|
||||
this.productsService = productsService;
|
||||
this.aiService = aiService;
|
||||
this.categoriesService = categoriesService;
|
||||
}
|
||||
findAll(tag) {
|
||||
return this.productsService.findAll({ tag });
|
||||
}
|
||||
findAllTags() {
|
||||
return this.productsService.findAllTags();
|
||||
}
|
||||
findDuplicates() {
|
||||
return this.productsService.findDuplicateCandidates();
|
||||
}
|
||||
previewMerge(sourceProductId, targetProductId) {
|
||||
return this.productsService.previewMerge(sourceProductId, targetProductId);
|
||||
}
|
||||
backfillCanonical() {
|
||||
return this.productsService.backfillCanonicalNames();
|
||||
}
|
||||
findPending() {
|
||||
return this.productsService.findPending();
|
||||
}
|
||||
aiCategorizeBulk(body) {
|
||||
return this.productsService.aiCategorizeBulk(body.productIds);
|
||||
}
|
||||
findDeleted() {
|
||||
return this.productsService.findDeleted();
|
||||
}
|
||||
findMine(req) {
|
||||
return this.productsService.findByOwner(req.user.id);
|
||||
}
|
||||
findOne(id) {
|
||||
return this.productsService.findOne(id);
|
||||
}
|
||||
createPrivate(body, req) {
|
||||
return this.productsService.createPrivate(body, req.user.id);
|
||||
}
|
||||
async suggestCategory(id) {
|
||||
const product = await this.productsService.findOne(id);
|
||||
const categories = await this.categoriesService.findFlattened();
|
||||
return this.aiService.suggestCategory(product.canonicalName ?? product.name, categories);
|
||||
}
|
||||
create(body, req) {
|
||||
return this.productsService.create(body, req.user.id);
|
||||
}
|
||||
createPending(body, req) {
|
||||
return this.productsService.createPending(body, req.user.id);
|
||||
}
|
||||
merge(body) {
|
||||
return this.productsService.merge(body.sourceProductId, body.targetProductId);
|
||||
}
|
||||
updateCanonicalName(id, body) {
|
||||
return this.productsService.updateCanonicalName(id, body.canonicalName);
|
||||
}
|
||||
setTags(id, body) {
|
||||
return this.productsService.setTags(id, body.tags);
|
||||
}
|
||||
upsertNutrition(id, body) {
|
||||
return this.productsService.upsertNutrition(id, body);
|
||||
}
|
||||
update(id, body) {
|
||||
return this.productsService.update(id, body);
|
||||
}
|
||||
permanentDelete(id) {
|
||||
return this.productsService.permanentDelete(id);
|
||||
}
|
||||
remove(id) {
|
||||
return this.productsService.remove(id);
|
||||
}
|
||||
setStatus(id, body) {
|
||||
return this.productsService.setStatus(id, body.status);
|
||||
}
|
||||
restore(id) {
|
||||
return this.productsService.restore(id);
|
||||
}
|
||||
resetAll() {
|
||||
return this.productsService.resetAll();
|
||||
}
|
||||
bulkUpdate(body) {
|
||||
return this.productsService.bulkUpdate(body.ids, { categoryId: body.categoryId });
|
||||
}
|
||||
};
|
||||
exports.ProductsController = ProductsController;
|
||||
__decorate([
|
||||
(0, public_decorator_1.Public)(),
|
||||
(0, common_1.Get)(),
|
||||
__param(0, (0, common_1.Query)('tag')),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [String]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "findAll", null);
|
||||
__decorate([
|
||||
(0, public_decorator_1.Public)(),
|
||||
(0, common_1.Get)('tags'),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "findAllTags", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Get)('duplicates'),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "findDuplicates", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Get)('merge-preview'),
|
||||
__param(0, (0, common_1.Query)('sourceProductId', common_1.ParseIntPipe)),
|
||||
__param(1, (0, common_1.Query)('targetProductId', common_1.ParseIntPipe)),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, Number]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "previewMerge", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Post)('backfill-canonical'),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "backfillCanonical", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Get)('pending'),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "findPending", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Post)('ai-categorize-bulk'),
|
||||
(0, throttler_1.Throttle)({ default: { ttl: 60_000, limit: 5 } }),
|
||||
(0, common_1.HttpCode)(200),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [ai_categorize_bulk_dto_1.AiCategorizeBulkDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "aiCategorizeBulk", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Get)('deleted'),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "findDeleted", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)('mine'),
|
||||
__param(0, (0, common_1.Request)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "findMine", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)(':id'),
|
||||
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "findOne", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('private'),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__param(1, (0, common_1.Request)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [create_product_dto_1.CreateProductDto, Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "createPrivate", null);
|
||||
__decorate([
|
||||
(0, common_1.UseGuards)(premium_or_admin_guard_1.PremiumOrAdminGuard),
|
||||
(0, common_1.Get)(':id/suggest-category'),
|
||||
(0, throttler_1.Throttle)({ default: { ttl: 60_000, limit: 20 } }),
|
||||
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], ProductsController.prototype, "suggestCategory", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Post)(),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__param(1, (0, common_1.Request)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [create_product_dto_1.CreateProductDto, Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "create", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('pending'),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__param(1, (0, common_1.Request)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [create_product_dto_1.CreateProductDto, Object]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "createPending", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Post)('merge'),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [merge_products_dto_1.MergeProductsDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "merge", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Patch)(':id/canonical-name'),
|
||||
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
||||
__param(1, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, update_canonical_name_dto_1.UpdateCanonicalNameDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "updateCanonicalName", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Put)(':id/tags'),
|
||||
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
||||
__param(1, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, set_tags_dto_1.SetTagsDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "setTags", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Put)(':id/nutrition'),
|
||||
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
||||
__param(1, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, upsert_nutrition_dto_1.UpsertNutritionDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "upsertNutrition", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Patch)(':id'),
|
||||
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
||||
__param(1, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, update_product_dto_1.UpdateProductDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "update", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Delete)(':id/permanent'),
|
||||
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "permanentDelete", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Delete)(':id'),
|
||||
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "remove", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Patch)(':id/status'),
|
||||
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
||||
__param(1, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number, set_product_status_dto_1.SetProductStatusDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "setStatus", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Post)(':id/restore'),
|
||||
__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Number]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "restore", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Post)('reset-all'),
|
||||
(0, common_1.HttpCode)(200),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "resetAll", null);
|
||||
__decorate([
|
||||
(0, roles_decorator_1.Roles)('admin'),
|
||||
(0, common_1.Post)('bulk-update'),
|
||||
(0, common_1.HttpCode)(200),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [bulk_update_products_dto_1.BulkUpdateProductsDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], ProductsController.prototype, "bulkUpdate", null);
|
||||
exports.ProductsController = ProductsController = __decorate([
|
||||
(0, common_1.Controller)('products'),
|
||||
__metadata("design:paramtypes", [products_service_1.ProductsService,
|
||||
ai_service_1.AiService,
|
||||
categories_service_1.CategoriesService])
|
||||
], ProductsController);
|
||||
//# sourceMappingURL=products.controller.js.map
|
||||
File diff suppressed because one or more lines are too long
+2
@@ -0,0 +1,2 @@
|
||||
export declare class ProductsModule {
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ProductsModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const products_controller_1 = require("./products.controller");
|
||||
const products_service_1 = require("./products.service");
|
||||
const ai_module_1 = require("../ai/ai.module");
|
||||
const categories_module_1 = require("../categories/categories.module");
|
||||
let ProductsModule = class ProductsModule {
|
||||
};
|
||||
exports.ProductsModule = ProductsModule;
|
||||
exports.ProductsModule = ProductsModule = __decorate([
|
||||
(0, common_1.Module)({
|
||||
imports: [ai_module_1.AiModule, categories_module_1.CategoriesModule],
|
||||
controllers: [products_controller_1.ProductsController],
|
||||
providers: [products_service_1.ProductsService],
|
||||
})
|
||||
], ProductsModule);
|
||||
//# sourceMappingURL=products.module.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"products.module.js","sourceRoot":"","sources":["../../src/products/products.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,+DAA2D;AAC3D,yDAAqD;AACrD,+CAA2C;AAC3C,uEAAmE;AAO5D,IAAM,cAAc,GAApB,MAAM,cAAc;CAAG,CAAA;AAAjB,wCAAc;yBAAd,cAAc;IAL1B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,oBAAQ,EAAE,oCAAgB,CAAC;QACrC,WAAW,EAAE,CAAC,wCAAkB,CAAC;QACjC,SAAS,EAAE,CAAC,kCAAe,CAAC;KAC7B,CAAC;GACW,cAAc,CAAG"}
|
||||
+458
@@ -0,0 +1,458 @@
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { CreateProductDto } from './dto/create-product.dto';
|
||||
import { UpdateProductDto } from './dto/update-product.dto';
|
||||
import { UpsertNutritionDto } from './dto/upsert-nutrition.dto';
|
||||
import { AiService } from '../ai/ai.service';
|
||||
import { CategoriesService } from '../categories/categories.service';
|
||||
export declare class ProductsService {
|
||||
private readonly prisma;
|
||||
private readonly aiService;
|
||||
private readonly categoriesService;
|
||||
constructor(prisma: PrismaService, aiService: AiService, categoriesService: CategoriesService);
|
||||
findAll(filters?: {
|
||||
tag?: string;
|
||||
}): Promise<({
|
||||
nutrition: {
|
||||
calories: number | null;
|
||||
protein: number | null;
|
||||
fat: number | null;
|
||||
carbohydrates: number | null;
|
||||
salt: number | null;
|
||||
sugar: number | null;
|
||||
fiber: number | null;
|
||||
id: number;
|
||||
productId: number;
|
||||
} | null;
|
||||
tags: ({
|
||||
tag: {
|
||||
name: string;
|
||||
id: number;
|
||||
};
|
||||
} & {
|
||||
productId: number;
|
||||
tagId: number;
|
||||
})[];
|
||||
categoryRef: ({
|
||||
parent: ({
|
||||
parent: {
|
||||
name: string;
|
||||
id: number;
|
||||
parentId: number | null;
|
||||
} | null;
|
||||
} & {
|
||||
name: string;
|
||||
id: number;
|
||||
parentId: number | null;
|
||||
}) | null;
|
||||
} & {
|
||||
name: string;
|
||||
id: number;
|
||||
parentId: number | null;
|
||||
}) | null;
|
||||
} & {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
})[]>;
|
||||
findByOwner(userId: number): Promise<{
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
}[]>;
|
||||
createPrivate(data: CreateProductDto, userId: number): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
findDuplicateCandidates(): Promise<{
|
||||
normalizedName: string;
|
||||
count: number;
|
||||
products: {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}[];
|
||||
}[]>;
|
||||
findOne(id: number): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
create(data: CreateProductDto, ownerId?: number): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
update(id: number, data: UpdateProductDto): Promise<{
|
||||
nutrition: {
|
||||
calories: number | null;
|
||||
protein: number | null;
|
||||
fat: number | null;
|
||||
carbohydrates: number | null;
|
||||
salt: number | null;
|
||||
sugar: number | null;
|
||||
fiber: number | null;
|
||||
id: number;
|
||||
productId: number;
|
||||
} | null;
|
||||
tags: ({
|
||||
tag: {
|
||||
name: string;
|
||||
id: number;
|
||||
};
|
||||
} & {
|
||||
productId: number;
|
||||
tagId: number;
|
||||
})[];
|
||||
} & {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
updateCanonicalName(id: number, canonicalName: string): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
findDeleted(): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}[]>;
|
||||
remove(id: number): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
permanentDelete(id: number): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
restore(id: number): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
private findProductByIdOrThrow;
|
||||
merge(sourceProductId: number, targetProductId: number): Promise<{
|
||||
message: string;
|
||||
sourceProductId: number;
|
||||
targetProductId: number;
|
||||
movedInventoryCount: number;
|
||||
softDeletedSource: {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
};
|
||||
}>;
|
||||
previewMerge(sourceProductId: number, targetProductId: number): Promise<{
|
||||
source: {
|
||||
inventoryCount: number;
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
};
|
||||
target: {
|
||||
inventoryCount: number;
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
};
|
||||
outcome: {
|
||||
inventoryItemsToMove: number;
|
||||
sourceWillBeSoftDeleted: boolean;
|
||||
targetWillRemainActive: boolean;
|
||||
};
|
||||
}>;
|
||||
backfillCanonicalNames(): Promise<{
|
||||
message: string;
|
||||
updatedCount: number;
|
||||
products: {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}[];
|
||||
}>;
|
||||
setTags(productId: number, tagNames: string[]): Promise<({
|
||||
nutrition: {
|
||||
calories: number | null;
|
||||
protein: number | null;
|
||||
fat: number | null;
|
||||
carbohydrates: number | null;
|
||||
salt: number | null;
|
||||
sugar: number | null;
|
||||
fiber: number | null;
|
||||
id: number;
|
||||
productId: number;
|
||||
} | null;
|
||||
tags: ({
|
||||
tag: {
|
||||
name: string;
|
||||
id: number;
|
||||
};
|
||||
} & {
|
||||
productId: number;
|
||||
tagId: number;
|
||||
})[];
|
||||
} & {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}) | null>;
|
||||
upsertNutrition(productId: number, data: UpsertNutritionDto): Promise<{
|
||||
calories: number | null;
|
||||
protein: number | null;
|
||||
fat: number | null;
|
||||
carbohydrates: number | null;
|
||||
salt: number | null;
|
||||
sugar: number | null;
|
||||
fiber: number | null;
|
||||
id: number;
|
||||
productId: number;
|
||||
}>;
|
||||
findAllTags(): Promise<{
|
||||
name: string;
|
||||
id: number;
|
||||
}[]>;
|
||||
resetAll(): Promise<{
|
||||
ok: boolean;
|
||||
}>;
|
||||
bulkUpdate(ids: number[], data: {
|
||||
categoryId?: number | null;
|
||||
}): Promise<{
|
||||
updated: number;
|
||||
}>;
|
||||
findUncategorized(): Promise<{
|
||||
id: number;
|
||||
name: string;
|
||||
canonicalName: string | null;
|
||||
}[]>;
|
||||
aiCategorizeBulk(productIds?: number[]): Promise<{
|
||||
productId: number;
|
||||
productName: string;
|
||||
suggestion: object;
|
||||
}[]>;
|
||||
findPending(): Promise<({
|
||||
owner: {
|
||||
id: number;
|
||||
username: string;
|
||||
};
|
||||
categoryRef: ({
|
||||
parent: {
|
||||
name: string;
|
||||
id: number;
|
||||
parentId: number | null;
|
||||
} | null;
|
||||
} & {
|
||||
name: string;
|
||||
id: number;
|
||||
parentId: number | null;
|
||||
}) | null;
|
||||
} & {
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
})[]>;
|
||||
createPending(data: CreateProductDto, userId: number): Promise<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}>;
|
||||
setStatus(id: number, status: string): import(".prisma/client").Prisma.Prisma__ProductClient<{
|
||||
category: string | null;
|
||||
status: string;
|
||||
name: string;
|
||||
categoryId: number | null;
|
||||
canonicalName: string | null;
|
||||
id: number;
|
||||
normalizedName: string;
|
||||
isActive: boolean;
|
||||
deletedAt: Date | null;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
ownerId: number;
|
||||
isPrivate: boolean;
|
||||
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
|
||||
}
|
||||
+425
@@ -0,0 +1,425 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ProductsService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const prisma_service_1 = require("../prisma/prisma.service");
|
||||
const normalize_name_1 = require("../common/utils/normalize-name");
|
||||
const ai_service_1 = require("../ai/ai.service");
|
||||
const categories_service_1 = require("../categories/categories.service");
|
||||
let ProductsService = class ProductsService {
|
||||
constructor(prisma, aiService, categoriesService) {
|
||||
this.prisma = prisma;
|
||||
this.aiService = aiService;
|
||||
this.categoriesService = categoriesService;
|
||||
}
|
||||
async findAll(filters) {
|
||||
return this.prisma.product.findMany({
|
||||
where: {
|
||||
isActive: true,
|
||||
isPrivate: false,
|
||||
...(filters?.tag
|
||||
? { tags: { some: { tag: { name: filters.tag } } } }
|
||||
: {}),
|
||||
},
|
||||
include: {
|
||||
tags: { include: { tag: true } },
|
||||
nutrition: true,
|
||||
categoryRef: { include: { parent: { include: { parent: true } } } },
|
||||
},
|
||||
orderBy: { name: 'asc' },
|
||||
});
|
||||
}
|
||||
async findByOwner(userId) {
|
||||
return this.prisma.product.findMany({
|
||||
where: { ownerId: userId, isPrivate: true, isActive: true },
|
||||
select: { id: true, name: true, canonicalName: true, categoryId: true },
|
||||
orderBy: { name: 'asc' },
|
||||
});
|
||||
}
|
||||
async createPrivate(data, userId) {
|
||||
const name = data.name.trim();
|
||||
const normalizedName = `private:${userId}:${(0, normalize_name_1.normalizeName)(name)}`;
|
||||
const existing = await this.prisma.product.findUnique({
|
||||
where: { normalizedName },
|
||||
});
|
||||
if (existing && existing.isActive)
|
||||
return existing;
|
||||
if (existing) {
|
||||
return this.prisma.product.update({
|
||||
where: { id: existing.id },
|
||||
data: { isActive: true, deletedAt: null, name, canonicalName: name },
|
||||
});
|
||||
}
|
||||
return this.prisma.product.create({
|
||||
data: {
|
||||
name,
|
||||
normalizedName,
|
||||
canonicalName: name,
|
||||
isActive: true,
|
||||
isPrivate: true,
|
||||
ownerId: userId,
|
||||
...(data.categoryId != null ? { categoryId: data.categoryId } : {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
async findDuplicateCandidates() {
|
||||
const products = await this.prisma.product.findMany({
|
||||
where: {
|
||||
isActive: true,
|
||||
},
|
||||
orderBy: {
|
||||
name: 'asc',
|
||||
},
|
||||
});
|
||||
const grouped = new Map();
|
||||
for (const product of products) {
|
||||
const key = product.normalizedName;
|
||||
if (!grouped.has(key)) {
|
||||
grouped.set(key, []);
|
||||
}
|
||||
grouped.get(key).push(product);
|
||||
}
|
||||
return Array.from(grouped.entries())
|
||||
.filter(([, items]) => items.length > 1)
|
||||
.map(([normalizedName, items]) => ({
|
||||
normalizedName,
|
||||
count: items.length,
|
||||
products: items,
|
||||
}));
|
||||
}
|
||||
async findOne(id) {
|
||||
const product = await this.prisma.product.findUnique({
|
||||
where: { id },
|
||||
});
|
||||
if (!product) {
|
||||
throw new common_1.NotFoundException(`Product with id ${id} not found`);
|
||||
}
|
||||
return product;
|
||||
}
|
||||
async create(data, ownerId) {
|
||||
const name = data.name.trim();
|
||||
const normalizedName = (0, normalize_name_1.normalizeName)(name);
|
||||
const existing = await this.prisma.product.findUnique({
|
||||
where: { normalizedName },
|
||||
});
|
||||
if (existing) {
|
||||
if (!existing.isActive) {
|
||||
return this.prisma.product.update({
|
||||
where: { id: existing.id },
|
||||
data: {
|
||||
isActive: true,
|
||||
deletedAt: null,
|
||||
name,
|
||||
canonicalName: name,
|
||||
},
|
||||
});
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
if (!ownerId) {
|
||||
throw new Error('ownerId är obligatorisk för att skapa en produkt');
|
||||
}
|
||||
return this.prisma.product.create({
|
||||
data: {
|
||||
ownerId,
|
||||
name,
|
||||
normalizedName,
|
||||
canonicalName: name,
|
||||
isActive: true,
|
||||
deletedAt: null,
|
||||
...(data.categoryId != null ? { categoryId: data.categoryId } : {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
async update(id, data) {
|
||||
await this.findOne(id);
|
||||
const updateData = {};
|
||||
if (typeof data.name === 'string') {
|
||||
const name = data.name.trim();
|
||||
const normalizedName = (0, normalize_name_1.normalizeName)(name);
|
||||
const existing = await this.prisma.product.findUnique({
|
||||
where: { normalizedName },
|
||||
});
|
||||
if (existing && existing.id !== id) {
|
||||
throw new Error('Det finns redan en annan produkt med detta namn. Välj ett unikt namn.');
|
||||
}
|
||||
updateData.name = name;
|
||||
updateData.normalizedName = normalizedName;
|
||||
}
|
||||
if (typeof data.canonicalName === 'string') {
|
||||
updateData.canonicalName = data.canonicalName.trim() || undefined;
|
||||
}
|
||||
if (typeof data.category === 'string') {
|
||||
updateData.category = data.category.trim() || null;
|
||||
}
|
||||
if ('categoryId' in data) {
|
||||
updateData.categoryId = data.categoryId ?? null;
|
||||
}
|
||||
return this.prisma.product.update({
|
||||
where: { id },
|
||||
data: updateData,
|
||||
include: { tags: { include: { tag: true } }, nutrition: true },
|
||||
});
|
||||
}
|
||||
async updateCanonicalName(id, canonicalName) {
|
||||
await this.findOne(id);
|
||||
const cleaned = canonicalName.trim();
|
||||
return this.prisma.product.update({
|
||||
where: { id },
|
||||
data: {
|
||||
canonicalName: cleaned,
|
||||
},
|
||||
});
|
||||
}
|
||||
async findDeleted() {
|
||||
return this.prisma.product.findMany({
|
||||
where: { isActive: false },
|
||||
orderBy: { deletedAt: 'desc' },
|
||||
});
|
||||
}
|
||||
async remove(id) {
|
||||
await this.findOne(id);
|
||||
return this.prisma.product.update({
|
||||
where: { id },
|
||||
data: {
|
||||
isActive: false,
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
});
|
||||
}
|
||||
async permanentDelete(id) {
|
||||
await this.findOne(id);
|
||||
await this.prisma.productTag.deleteMany({ where: { productId: id } });
|
||||
await this.prisma.userProduct.deleteMany({ where: { productId: id } });
|
||||
return this.prisma.product.delete({ where: { id } });
|
||||
}
|
||||
async restore(id) {
|
||||
const product = await this.findOne(id);
|
||||
if (product.isActive) {
|
||||
return product;
|
||||
}
|
||||
return this.prisma.product.update({
|
||||
where: { id },
|
||||
data: {
|
||||
isActive: true,
|
||||
deletedAt: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
async findProductByIdOrThrow(id, label) {
|
||||
const product = await this.prisma.product.findUnique({ where: { id } });
|
||||
if (!product) {
|
||||
throw new common_1.NotFoundException(`${label} product with id ${id} not found`);
|
||||
}
|
||||
return product;
|
||||
}
|
||||
async merge(sourceProductId, targetProductId) {
|
||||
if (sourceProductId === targetProductId) {
|
||||
throw new Error('sourceProductId och targetProductId kan inte vara samma');
|
||||
}
|
||||
const source = await this.findProductByIdOrThrow(sourceProductId, 'Source');
|
||||
const target = await this.findProductByIdOrThrow(targetProductId, 'Target');
|
||||
return this.prisma.$transaction(async (tx) => {
|
||||
const movedInventoryCount = await tx.inventoryItem.updateMany({
|
||||
where: { productId: sourceProductId },
|
||||
data: { productId: targetProductId },
|
||||
});
|
||||
const softDeletedSource = await tx.product.update({
|
||||
where: { id: sourceProductId },
|
||||
data: {
|
||||
isActive: false,
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
});
|
||||
return {
|
||||
message: 'Products merged successfully',
|
||||
sourceProductId,
|
||||
targetProductId,
|
||||
movedInventoryCount: movedInventoryCount.count,
|
||||
softDeletedSource,
|
||||
};
|
||||
});
|
||||
}
|
||||
async previewMerge(sourceProductId, targetProductId) {
|
||||
if (sourceProductId === targetProductId) {
|
||||
throw new Error('sourceProductId och targetProductId kan inte vara samma');
|
||||
}
|
||||
const [source, target, sourceInventoryCount, targetInventoryCount] = await Promise.all([
|
||||
this.findProductByIdOrThrow(sourceProductId, 'Source'),
|
||||
this.findProductByIdOrThrow(targetProductId, 'Target'),
|
||||
this.prisma.inventoryItem.count({
|
||||
where: { productId: sourceProductId },
|
||||
}),
|
||||
this.prisma.inventoryItem.count({
|
||||
where: { productId: targetProductId },
|
||||
}),
|
||||
]);
|
||||
return {
|
||||
source: {
|
||||
...source,
|
||||
inventoryCount: sourceInventoryCount,
|
||||
},
|
||||
target: {
|
||||
...target,
|
||||
inventoryCount: targetInventoryCount,
|
||||
},
|
||||
outcome: {
|
||||
inventoryItemsToMove: sourceInventoryCount,
|
||||
sourceWillBeSoftDeleted: true,
|
||||
targetWillRemainActive: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
async backfillCanonicalNames() {
|
||||
const products = await this.prisma.product.findMany({
|
||||
where: {
|
||||
canonicalName: null,
|
||||
},
|
||||
});
|
||||
const results = await this.prisma.$transaction(products.map((product) => this.prisma.product.update({
|
||||
where: { id: product.id },
|
||||
data: {
|
||||
canonicalName: product.name,
|
||||
},
|
||||
})));
|
||||
return {
|
||||
message: 'Canonical names backfilled successfully',
|
||||
updatedCount: results.length,
|
||||
products: results,
|
||||
};
|
||||
}
|
||||
async setTags(productId, tagNames) {
|
||||
await this.findOne(productId);
|
||||
const tags = await this.prisma.$transaction(tagNames.map((name) => this.prisma.tag.upsert({
|
||||
where: { name },
|
||||
create: { name },
|
||||
update: {},
|
||||
})));
|
||||
await this.prisma.productTag.deleteMany({ where: { productId } });
|
||||
if (tags.length > 0) {
|
||||
await this.prisma.productTag.createMany({
|
||||
data: tags.map((tag) => ({ productId, tagId: tag.id })),
|
||||
skipDuplicates: true,
|
||||
});
|
||||
}
|
||||
return this.prisma.product.findUnique({
|
||||
where: { id: productId },
|
||||
include: { tags: { include: { tag: true } }, nutrition: true },
|
||||
});
|
||||
}
|
||||
async upsertNutrition(productId, data) {
|
||||
await this.findOne(productId);
|
||||
return this.prisma.nutrition.upsert({
|
||||
where: { productId },
|
||||
create: { productId, ...data },
|
||||
update: { ...data },
|
||||
});
|
||||
}
|
||||
async findAllTags() {
|
||||
return this.prisma.tag.findMany({ orderBy: { name: 'asc' } });
|
||||
}
|
||||
async resetAll() {
|
||||
await this.prisma.$transaction([
|
||||
this.prisma.receiptAlias.deleteMany(),
|
||||
this.prisma.inventoryConsumption.deleteMany(),
|
||||
this.prisma.inventoryItem.deleteMany(),
|
||||
this.prisma.pantryItem.deleteMany(),
|
||||
this.prisma.nutrition.deleteMany(),
|
||||
this.prisma.productTag.deleteMany(),
|
||||
this.prisma.tag.deleteMany(),
|
||||
this.prisma.userProduct.deleteMany(),
|
||||
this.prisma.recipeIngredient.deleteMany(),
|
||||
this.prisma.product.deleteMany(),
|
||||
]);
|
||||
return { ok: true };
|
||||
}
|
||||
async bulkUpdate(ids, data) {
|
||||
const updateData = {};
|
||||
if ('categoryId' in data) {
|
||||
updateData.categoryId = data.categoryId;
|
||||
}
|
||||
if (Object.keys(updateData).length === 0)
|
||||
return { updated: 0 };
|
||||
await this.prisma.product.updateMany({ where: { id: { in: ids } }, data: updateData });
|
||||
return { updated: ids.length };
|
||||
}
|
||||
async findUncategorized() {
|
||||
return this.prisma.product.findMany({
|
||||
where: { isActive: true, categoryId: null, status: 'active' },
|
||||
select: { id: true, name: true, canonicalName: true },
|
||||
orderBy: { name: 'asc' },
|
||||
});
|
||||
}
|
||||
async aiCategorizeBulk(productIds) {
|
||||
const categories = await this.categoriesService.findFlattened();
|
||||
let products;
|
||||
if (productIds && productIds.length > 0) {
|
||||
const found = await Promise.all(productIds.map((id) => this.findOne(id)));
|
||||
products = found.map((p) => ({ id: p.id, name: p.canonicalName ?? p.name }));
|
||||
}
|
||||
else {
|
||||
products = await this.findUncategorized();
|
||||
}
|
||||
const results = [];
|
||||
for (const product of products) {
|
||||
const suggestion = await this.aiService.suggestCategory(product.name, categories);
|
||||
results.push({ productId: product.id, productName: product.name, suggestion });
|
||||
}
|
||||
return results;
|
||||
}
|
||||
async findPending() {
|
||||
return this.prisma.product.findMany({
|
||||
where: { status: 'pending' },
|
||||
include: {
|
||||
categoryRef: { include: { parent: true } },
|
||||
owner: { select: { id: true, username: true } },
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
});
|
||||
}
|
||||
async createPending(data, userId) {
|
||||
const name = data.name.trim();
|
||||
const normalizedName = (0, normalize_name_1.normalizeName)(name);
|
||||
const existing = await this.prisma.product.findUnique({
|
||||
where: { normalizedName },
|
||||
});
|
||||
if (existing) {
|
||||
if (existing.isActive && existing.status === 'active') {
|
||||
return existing;
|
||||
}
|
||||
if (existing.status === 'pending') {
|
||||
return existing;
|
||||
}
|
||||
}
|
||||
return this.prisma.product.create({
|
||||
data: {
|
||||
name,
|
||||
normalizedName,
|
||||
canonicalName: name,
|
||||
isActive: false,
|
||||
status: 'pending',
|
||||
ownerId: userId,
|
||||
},
|
||||
});
|
||||
}
|
||||
setStatus(id, status) {
|
||||
return this.prisma.product.update({ where: { id }, data: { status } });
|
||||
}
|
||||
};
|
||||
exports.ProductsService = ProductsService;
|
||||
exports.ProductsService = ProductsService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService,
|
||||
ai_service_1.AiService,
|
||||
categories_service_1.CategoriesService])
|
||||
], ProductsService);
|
||||
//# sourceMappingURL=products.service.js.map
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user