proflores-db-model 0.2.47 → 0.2.49
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/dist/models/apu/Apu.d.ts +2 -0
- package/dist/models/apu/Apu.js +5 -0
- package/dist/models/apu/Concept.d.ts +13 -1
- package/dist/models/apu/Concept.js +19 -2
- package/dist/models/apu/IndirectCostCalculator.d.ts +37 -0
- package/dist/models/apu/IndirectCostCalculator.js +79 -0
- package/dist/models/apu/IndirectCostConfig.d.ts +19 -0
- package/dist/models/apu/IndirectCostConfig.js +69 -0
- package/dist/models/apu/IndirectCostItem.d.ts +14 -0
- package/dist/models/apu/IndirectCostItem.js +64 -0
- package/dist/models/apu/IndirectCostTemplate.d.ts +10 -0
- package/dist/models/apu/IndirectCostTemplate.js +46 -0
- package/dist/models/apu/IndirectCostTemplateItem.d.ts +19 -0
- package/dist/models/apu/IndirectCostTemplateItem.js +64 -0
- package/dist/models/apu/index.d.ts +6 -0
- package/dist/models/apu/index.js +17 -1
- package/package.json +1 -1
- package/src/models/apu/Apu.ts +4 -0
- package/src/models/apu/Concept.ts +19 -2
- package/src/models/apu/IndirectCostCalculator.ts +92 -0
- package/src/models/apu/IndirectCostConfig.ts +48 -0
- package/src/models/apu/IndirectCostItem.ts +42 -0
- package/src/models/apu/IndirectCostTemplate.ts +27 -0
- package/src/models/apu/IndirectCostTemplateItem.ts +44 -0
- package/src/models/apu/index.ts +11 -1
package/dist/models/apu/Apu.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ObjectLiteral } from "typeorm";
|
|
2
2
|
import { Concept } from "./Concept";
|
|
3
3
|
import { ApuItem } from "./ApuItem";
|
|
4
|
+
import { IndirectCostConfig } from "./IndirectCostConfig";
|
|
4
5
|
export declare class Apu implements ObjectLiteral {
|
|
5
6
|
idApu: number;
|
|
6
7
|
concept: Concept;
|
|
@@ -11,4 +12,5 @@ export declare class Apu implements ObjectLiteral {
|
|
|
11
12
|
profitPct: number;
|
|
12
13
|
notes?: string | null;
|
|
13
14
|
items?: ApuItem[];
|
|
15
|
+
indirectCostConfig?: IndirectCostConfig;
|
|
14
16
|
}
|
package/dist/models/apu/Apu.js
CHANGED
|
@@ -13,6 +13,7 @@ exports.Apu = void 0;
|
|
|
13
13
|
const typeorm_1 = require("typeorm");
|
|
14
14
|
const Concept_1 = require("./Concept");
|
|
15
15
|
const ApuItem_1 = require("./ApuItem");
|
|
16
|
+
const IndirectCostConfig_1 = require("./IndirectCostConfig");
|
|
16
17
|
let Apu = class Apu {
|
|
17
18
|
};
|
|
18
19
|
exports.Apu = Apu;
|
|
@@ -53,6 +54,10 @@ __decorate([
|
|
|
53
54
|
(0, typeorm_1.OneToMany)(() => ApuItem_1.ApuItem, (ai) => ai.apu, { cascade: true }),
|
|
54
55
|
__metadata("design:type", Array)
|
|
55
56
|
], Apu.prototype, "items", void 0);
|
|
57
|
+
__decorate([
|
|
58
|
+
(0, typeorm_1.OneToMany)(() => IndirectCostConfig_1.IndirectCostConfig, (config) => config.apu),
|
|
59
|
+
__metadata("design:type", IndirectCostConfig_1.IndirectCostConfig)
|
|
60
|
+
], Apu.prototype, "indirectCostConfig", void 0);
|
|
56
61
|
exports.Apu = Apu = __decorate([
|
|
57
62
|
(0, typeorm_1.Entity)("apu"),
|
|
58
63
|
(0, typeorm_1.Unique)("uq_apu_concept_version", ["concept", "version"]),
|
|
@@ -2,6 +2,18 @@ import { ObjectLiteral } from "typeorm";
|
|
|
2
2
|
import { UnitOfMeasure } from "../../entities/UnitOfMesure";
|
|
3
3
|
import { Apu } from "./Apu";
|
|
4
4
|
import { BudgetItem } from "./BudgetItem";
|
|
5
|
+
export declare enum ConceptCategory {
|
|
6
|
+
JARDINERIA = "JAR",
|
|
7
|
+
RIEGO = "RIE",
|
|
8
|
+
OBRAS_CIVILES = "OBR",
|
|
9
|
+
MOBILIARIO = "MOB",
|
|
10
|
+
TERRACERIAS = "TER",
|
|
11
|
+
MANTENIMIENTO = "MAN",
|
|
12
|
+
MATERIALES = "MAT",
|
|
13
|
+
MANO_DE_OBRA = "LAB",
|
|
14
|
+
HERRAMIENTAS = "TOOL",
|
|
15
|
+
FERTILIZACION = "FER"
|
|
16
|
+
}
|
|
5
17
|
export declare class Concept implements ObjectLiteral {
|
|
6
18
|
idConcept: number;
|
|
7
19
|
code?: string | null;
|
|
@@ -10,7 +22,7 @@ export declare class Concept implements ObjectLiteral {
|
|
|
10
22
|
unit: UnitOfMeasure;
|
|
11
23
|
satClave?: string | null;
|
|
12
24
|
satUnit?: string | null;
|
|
13
|
-
category?:
|
|
25
|
+
category?: ConceptCategory | null;
|
|
14
26
|
isActive: boolean;
|
|
15
27
|
apus?: Apu[];
|
|
16
28
|
budgetItems?: BudgetItem[];
|
|
@@ -9,12 +9,25 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.Concept = void 0;
|
|
12
|
+
exports.Concept = exports.ConceptCategory = void 0;
|
|
13
13
|
// apu/entities/Concept.ts
|
|
14
14
|
const typeorm_1 = require("typeorm");
|
|
15
15
|
const UnitOfMesure_1 = require("../../entities/UnitOfMesure"); // <-- ajusta tu ruta real
|
|
16
16
|
const Apu_1 = require("./Apu");
|
|
17
17
|
const BudgetItem_1 = require("./BudgetItem");
|
|
18
|
+
var ConceptCategory;
|
|
19
|
+
(function (ConceptCategory) {
|
|
20
|
+
ConceptCategory["JARDINERIA"] = "JAR";
|
|
21
|
+
ConceptCategory["RIEGO"] = "RIE";
|
|
22
|
+
ConceptCategory["OBRAS_CIVILES"] = "OBR";
|
|
23
|
+
ConceptCategory["MOBILIARIO"] = "MOB";
|
|
24
|
+
ConceptCategory["TERRACERIAS"] = "TER";
|
|
25
|
+
ConceptCategory["MANTENIMIENTO"] = "MAN";
|
|
26
|
+
ConceptCategory["MATERIALES"] = "MAT";
|
|
27
|
+
ConceptCategory["MANO_DE_OBRA"] = "LAB";
|
|
28
|
+
ConceptCategory["HERRAMIENTAS"] = "TOOL";
|
|
29
|
+
ConceptCategory["FERTILIZACION"] = "FER";
|
|
30
|
+
})(ConceptCategory || (exports.ConceptCategory = ConceptCategory = {}));
|
|
18
31
|
let Concept = class Concept {
|
|
19
32
|
};
|
|
20
33
|
exports.Concept = Concept;
|
|
@@ -48,7 +61,11 @@ __decorate([
|
|
|
48
61
|
__metadata("design:type", Object)
|
|
49
62
|
], Concept.prototype, "satUnit", void 0);
|
|
50
63
|
__decorate([
|
|
51
|
-
(0, typeorm_1.Column)(
|
|
64
|
+
(0, typeorm_1.Column)({
|
|
65
|
+
type: "enum",
|
|
66
|
+
enum: ConceptCategory,
|
|
67
|
+
nullable: true
|
|
68
|
+
}),
|
|
52
69
|
__metadata("design:type", Object)
|
|
53
70
|
], Concept.prototype, "category", void 0);
|
|
54
71
|
__decorate([
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { IndirectCostConfig } from "./IndirectCostConfig";
|
|
2
|
+
export declare class IndirectCostCalculator {
|
|
3
|
+
/**
|
|
4
|
+
* Calcula el factor total de costos indirectos para una configuración
|
|
5
|
+
* @param config Configuración de costos indirectos
|
|
6
|
+
* @returns Factor total (0..1)
|
|
7
|
+
*/
|
|
8
|
+
static calculateTotalIndirectFactor(config: IndirectCostConfig): number;
|
|
9
|
+
/**
|
|
10
|
+
* Calcula el desglose de costos indirectos por categoría
|
|
11
|
+
* @param config Configuración de costos indirectos
|
|
12
|
+
* @param directCost Costo directo base
|
|
13
|
+
* @returns Desglose por categoría
|
|
14
|
+
*/
|
|
15
|
+
static calculateIndirectCostBreakdown(config: IndirectCostConfig, directCost: number): {
|
|
16
|
+
[category: string]: {
|
|
17
|
+
percentage: number;
|
|
18
|
+
amount: number;
|
|
19
|
+
name: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Calcula el costo total incluyendo indirectos
|
|
24
|
+
* @param directCost Costo directo
|
|
25
|
+
* @param config Configuración de costos indirectos
|
|
26
|
+
* @returns Costo total
|
|
27
|
+
*/
|
|
28
|
+
static calculateTotalCost(directCost: number, config: IndirectCostConfig): number;
|
|
29
|
+
/**
|
|
30
|
+
* Crea una configuración de costos indirectos desde una plantilla
|
|
31
|
+
* @param template Plantilla base
|
|
32
|
+
* @param scope Ámbito de aplicación (APU o PROJECT)
|
|
33
|
+
* @returns Configuración de costos indirectos
|
|
34
|
+
*/
|
|
35
|
+
static createConfigFromTemplate(template: any, // IndirectCostTemplate
|
|
36
|
+
scope: "APU" | "PROJECT"): Partial<IndirectCostConfig>;
|
|
37
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IndirectCostCalculator = void 0;
|
|
4
|
+
class IndirectCostCalculator {
|
|
5
|
+
/**
|
|
6
|
+
* Calcula el factor total de costos indirectos para una configuración
|
|
7
|
+
* @param config Configuración de costos indirectos
|
|
8
|
+
* @returns Factor total (0..1)
|
|
9
|
+
*/
|
|
10
|
+
static calculateTotalIndirectFactor(config) {
|
|
11
|
+
if (!config.items || config.items.length === 0) {
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
return config.items
|
|
15
|
+
.filter(item => item.isActive)
|
|
16
|
+
.reduce((total, item) => total + item.percentage, 0);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Calcula el desglose de costos indirectos por categoría
|
|
20
|
+
* @param config Configuración de costos indirectos
|
|
21
|
+
* @param directCost Costo directo base
|
|
22
|
+
* @returns Desglose por categoría
|
|
23
|
+
*/
|
|
24
|
+
static calculateIndirectCostBreakdown(config, directCost) {
|
|
25
|
+
const breakdown = {};
|
|
26
|
+
if (!config.items) {
|
|
27
|
+
return breakdown;
|
|
28
|
+
}
|
|
29
|
+
config.items
|
|
30
|
+
.filter(item => item.isActive)
|
|
31
|
+
.forEach(item => {
|
|
32
|
+
breakdown[item.category] = {
|
|
33
|
+
percentage: item.percentage,
|
|
34
|
+
amount: directCost * item.percentage + (item.fixedAmount || 0),
|
|
35
|
+
name: item.name
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
return breakdown;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Calcula el costo total incluyendo indirectos
|
|
42
|
+
* @param directCost Costo directo
|
|
43
|
+
* @param config Configuración de costos indirectos
|
|
44
|
+
* @returns Costo total
|
|
45
|
+
*/
|
|
46
|
+
static calculateTotalCost(directCost, config) {
|
|
47
|
+
var _a;
|
|
48
|
+
const indirectFactor = this.calculateTotalIndirectFactor(config);
|
|
49
|
+
const indirectCost = directCost * indirectFactor;
|
|
50
|
+
// Agregar montos fijos si existen
|
|
51
|
+
const fixedAmounts = ((_a = config.items) === null || _a === void 0 ? void 0 : _a.filter(item => item.isActive && item.fixedAmount).reduce((sum, item) => sum + (item.fixedAmount || 0), 0)) || 0;
|
|
52
|
+
return directCost + indirectCost + fixedAmounts;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Crea una configuración de costos indirectos desde una plantilla
|
|
56
|
+
* @param template Plantilla base
|
|
57
|
+
* @param scope Ámbito de aplicación (APU o PROJECT)
|
|
58
|
+
* @returns Configuración de costos indirectos
|
|
59
|
+
*/
|
|
60
|
+
static createConfigFromTemplate(template, // IndirectCostTemplate
|
|
61
|
+
scope) {
|
|
62
|
+
var _a;
|
|
63
|
+
return {
|
|
64
|
+
scope: scope,
|
|
65
|
+
template: template,
|
|
66
|
+
name: `Config basada en ${template.name}`,
|
|
67
|
+
description: template.description,
|
|
68
|
+
items: (_a = template.items) === null || _a === void 0 ? void 0 : _a.map((templateItem) => ({
|
|
69
|
+
category: templateItem.category,
|
|
70
|
+
name: templateItem.name,
|
|
71
|
+
description: templateItem.description,
|
|
72
|
+
percentage: templateItem.percentage,
|
|
73
|
+
sortOrder: templateItem.sortOrder,
|
|
74
|
+
isActive: true
|
|
75
|
+
}))
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.IndirectCostCalculator = IndirectCostCalculator;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ObjectLiteral } from "typeorm";
|
|
2
|
+
import { Apu } from "./Apu";
|
|
3
|
+
import { Project } from "./Project";
|
|
4
|
+
import { IndirectCostTemplate } from "./IndirectCostTemplate";
|
|
5
|
+
import { IndirectCostItem } from "./IndirectCostItem";
|
|
6
|
+
export declare enum IndirectCostScope {
|
|
7
|
+
APU = "APU",// Aplica solo a un APU específico
|
|
8
|
+
PROJECT = "PROJECT"
|
|
9
|
+
}
|
|
10
|
+
export declare class IndirectCostConfig implements ObjectLiteral {
|
|
11
|
+
idIndirectCostConfig: number;
|
|
12
|
+
scope: IndirectCostScope;
|
|
13
|
+
apu?: Apu | null;
|
|
14
|
+
project?: Project | null;
|
|
15
|
+
template?: IndirectCostTemplate | null;
|
|
16
|
+
name?: string | null;
|
|
17
|
+
description?: string | null;
|
|
18
|
+
items?: IndirectCostItem[];
|
|
19
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.IndirectCostConfig = exports.IndirectCostScope = void 0;
|
|
13
|
+
// apu/entities/IndirectCostConfig.ts
|
|
14
|
+
const typeorm_1 = require("typeorm");
|
|
15
|
+
const Apu_1 = require("./Apu");
|
|
16
|
+
const Project_1 = require("./Project");
|
|
17
|
+
const IndirectCostTemplate_1 = require("./IndirectCostTemplate");
|
|
18
|
+
const IndirectCostItem_1 = require("./IndirectCostItem");
|
|
19
|
+
var IndirectCostScope;
|
|
20
|
+
(function (IndirectCostScope) {
|
|
21
|
+
IndirectCostScope["APU"] = "APU";
|
|
22
|
+
IndirectCostScope["PROJECT"] = "PROJECT"; // Aplica a todo el proyecto
|
|
23
|
+
})(IndirectCostScope || (exports.IndirectCostScope = IndirectCostScope = {}));
|
|
24
|
+
let IndirectCostConfig = class IndirectCostConfig {
|
|
25
|
+
};
|
|
26
|
+
exports.IndirectCostConfig = IndirectCostConfig;
|
|
27
|
+
__decorate([
|
|
28
|
+
(0, typeorm_1.PrimaryGeneratedColumn)("increment"),
|
|
29
|
+
__metadata("design:type", Number)
|
|
30
|
+
], IndirectCostConfig.prototype, "idIndirectCostConfig", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, typeorm_1.Column)({
|
|
33
|
+
type: "enum",
|
|
34
|
+
enum: IndirectCostScope
|
|
35
|
+
}),
|
|
36
|
+
__metadata("design:type", String)
|
|
37
|
+
], IndirectCostConfig.prototype, "scope", void 0);
|
|
38
|
+
__decorate([
|
|
39
|
+
(0, typeorm_1.ManyToOne)(() => Apu_1.Apu, { nullable: true, onDelete: "CASCADE" }),
|
|
40
|
+
(0, typeorm_1.JoinColumn)({ name: "idApu" }),
|
|
41
|
+
__metadata("design:type", Object)
|
|
42
|
+
], IndirectCostConfig.prototype, "apu", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
(0, typeorm_1.ManyToOne)(() => Project_1.Project, { nullable: true, onDelete: "CASCADE" }),
|
|
45
|
+
(0, typeorm_1.JoinColumn)({ name: "idProject" }),
|
|
46
|
+
__metadata("design:type", Object)
|
|
47
|
+
], IndirectCostConfig.prototype, "project", void 0);
|
|
48
|
+
__decorate([
|
|
49
|
+
(0, typeorm_1.ManyToOne)(() => IndirectCostTemplate_1.IndirectCostTemplate, { nullable: true }),
|
|
50
|
+
(0, typeorm_1.JoinColumn)({ name: "idIndirectCostTemplate" }),
|
|
51
|
+
__metadata("design:type", Object)
|
|
52
|
+
], IndirectCostConfig.prototype, "template", void 0);
|
|
53
|
+
__decorate([
|
|
54
|
+
(0, typeorm_1.Column)("varchar", { length: 255, nullable: true }),
|
|
55
|
+
__metadata("design:type", Object)
|
|
56
|
+
], IndirectCostConfig.prototype, "name", void 0);
|
|
57
|
+
__decorate([
|
|
58
|
+
(0, typeorm_1.Column)("text", { nullable: true }),
|
|
59
|
+
__metadata("design:type", Object)
|
|
60
|
+
], IndirectCostConfig.prototype, "description", void 0);
|
|
61
|
+
__decorate([
|
|
62
|
+
(0, typeorm_1.OneToMany)(() => IndirectCostItem_1.IndirectCostItem, (item) => item.config, { cascade: true }),
|
|
63
|
+
__metadata("design:type", Array)
|
|
64
|
+
], IndirectCostConfig.prototype, "items", void 0);
|
|
65
|
+
exports.IndirectCostConfig = IndirectCostConfig = __decorate([
|
|
66
|
+
(0, typeorm_1.Entity)("indirect_cost_configs"),
|
|
67
|
+
(0, typeorm_1.Index)(["apu"], { unique: true, where: "scope = 'APU'" }),
|
|
68
|
+
(0, typeorm_1.Index)(["project"], { unique: true, where: "scope = 'PROJECT'" })
|
|
69
|
+
], IndirectCostConfig);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ObjectLiteral } from "typeorm";
|
|
2
|
+
import { IndirectCostConfig } from "./IndirectCostConfig";
|
|
3
|
+
import { IndirectCostCategory } from "./IndirectCostTemplateItem";
|
|
4
|
+
export declare class IndirectCostItem implements ObjectLiteral {
|
|
5
|
+
idIndirectCostItem: number;
|
|
6
|
+
config: IndirectCostConfig;
|
|
7
|
+
category: IndirectCostCategory;
|
|
8
|
+
name: string;
|
|
9
|
+
description?: string | null;
|
|
10
|
+
percentage: number;
|
|
11
|
+
fixedAmount?: number | null;
|
|
12
|
+
sortOrder: number;
|
|
13
|
+
isActive: boolean;
|
|
14
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.IndirectCostItem = void 0;
|
|
13
|
+
// apu/entities/IndirectCostItem.ts
|
|
14
|
+
const typeorm_1 = require("typeorm");
|
|
15
|
+
const IndirectCostConfig_1 = require("./IndirectCostConfig");
|
|
16
|
+
const IndirectCostTemplateItem_1 = require("./IndirectCostTemplateItem");
|
|
17
|
+
let IndirectCostItem = class IndirectCostItem {
|
|
18
|
+
};
|
|
19
|
+
exports.IndirectCostItem = IndirectCostItem;
|
|
20
|
+
__decorate([
|
|
21
|
+
(0, typeorm_1.PrimaryGeneratedColumn)("increment"),
|
|
22
|
+
__metadata("design:type", Number)
|
|
23
|
+
], IndirectCostItem.prototype, "idIndirectCostItem", void 0);
|
|
24
|
+
__decorate([
|
|
25
|
+
(0, typeorm_1.ManyToOne)(() => IndirectCostConfig_1.IndirectCostConfig, { nullable: false, onDelete: "CASCADE" }),
|
|
26
|
+
(0, typeorm_1.JoinColumn)({ name: "idIndirectCostConfig" }),
|
|
27
|
+
__metadata("design:type", IndirectCostConfig_1.IndirectCostConfig)
|
|
28
|
+
], IndirectCostItem.prototype, "config", void 0);
|
|
29
|
+
__decorate([
|
|
30
|
+
(0, typeorm_1.Column)({
|
|
31
|
+
type: "enum",
|
|
32
|
+
enum: IndirectCostTemplateItem_1.IndirectCostCategory
|
|
33
|
+
}),
|
|
34
|
+
__metadata("design:type", String)
|
|
35
|
+
], IndirectCostItem.prototype, "category", void 0);
|
|
36
|
+
__decorate([
|
|
37
|
+
(0, typeorm_1.Column)("varchar", { length: 255 }),
|
|
38
|
+
__metadata("design:type", String)
|
|
39
|
+
], IndirectCostItem.prototype, "name", void 0);
|
|
40
|
+
__decorate([
|
|
41
|
+
(0, typeorm_1.Column)("text", { nullable: true }),
|
|
42
|
+
__metadata("design:type", Object)
|
|
43
|
+
], IndirectCostItem.prototype, "description", void 0);
|
|
44
|
+
__decorate([
|
|
45
|
+
(0, typeorm_1.Column)("decimal", { precision: 5, scale: 4, default: 0 }),
|
|
46
|
+
__metadata("design:type", Number)
|
|
47
|
+
], IndirectCostItem.prototype, "percentage", void 0);
|
|
48
|
+
__decorate([
|
|
49
|
+
(0, typeorm_1.Column)("decimal", { precision: 18, scale: 2, nullable: true }),
|
|
50
|
+
__metadata("design:type", Object)
|
|
51
|
+
], IndirectCostItem.prototype, "fixedAmount", void 0);
|
|
52
|
+
__decorate([
|
|
53
|
+
(0, typeorm_1.Column)("int", { default: 0 }),
|
|
54
|
+
__metadata("design:type", Number)
|
|
55
|
+
], IndirectCostItem.prototype, "sortOrder", void 0);
|
|
56
|
+
__decorate([
|
|
57
|
+
(0, typeorm_1.Column)({ type: "boolean", default: true }),
|
|
58
|
+
__metadata("design:type", Boolean)
|
|
59
|
+
], IndirectCostItem.prototype, "isActive", void 0);
|
|
60
|
+
exports.IndirectCostItem = IndirectCostItem = __decorate([
|
|
61
|
+
(0, typeorm_1.Entity)("indirect_cost_items"),
|
|
62
|
+
(0, typeorm_1.Index)(["config", "category"], { unique: true }),
|
|
63
|
+
(0, typeorm_1.Check)(`"percentage" >= 0 AND "percentage" <= 1`)
|
|
64
|
+
], IndirectCostItem);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ObjectLiteral } from "typeorm";
|
|
2
|
+
import { IndirectCostTemplateItem } from "./IndirectCostTemplateItem";
|
|
3
|
+
export declare class IndirectCostTemplate implements ObjectLiteral {
|
|
4
|
+
idIndirectCostTemplate: number;
|
|
5
|
+
name: string;
|
|
6
|
+
description?: string | null;
|
|
7
|
+
projectType?: string | null;
|
|
8
|
+
isActive: boolean;
|
|
9
|
+
items?: IndirectCostTemplateItem[];
|
|
10
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.IndirectCostTemplate = void 0;
|
|
13
|
+
// apu/entities/IndirectCostTemplate.ts
|
|
14
|
+
const typeorm_1 = require("typeorm");
|
|
15
|
+
const IndirectCostTemplateItem_1 = require("./IndirectCostTemplateItem");
|
|
16
|
+
let IndirectCostTemplate = class IndirectCostTemplate {
|
|
17
|
+
};
|
|
18
|
+
exports.IndirectCostTemplate = IndirectCostTemplate;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, typeorm_1.PrimaryGeneratedColumn)("increment"),
|
|
21
|
+
__metadata("design:type", Number)
|
|
22
|
+
], IndirectCostTemplate.prototype, "idIndirectCostTemplate", void 0);
|
|
23
|
+
__decorate([
|
|
24
|
+
(0, typeorm_1.Column)("varchar", { length: 255, unique: true }),
|
|
25
|
+
__metadata("design:type", String)
|
|
26
|
+
], IndirectCostTemplate.prototype, "name", void 0);
|
|
27
|
+
__decorate([
|
|
28
|
+
(0, typeorm_1.Column)("text", { nullable: true }),
|
|
29
|
+
__metadata("design:type", Object)
|
|
30
|
+
], IndirectCostTemplate.prototype, "description", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, typeorm_1.Column)("varchar", { length: 64, nullable: true }),
|
|
33
|
+
__metadata("design:type", Object)
|
|
34
|
+
], IndirectCostTemplate.prototype, "projectType", void 0);
|
|
35
|
+
__decorate([
|
|
36
|
+
(0, typeorm_1.Column)({ type: "boolean", default: true }),
|
|
37
|
+
__metadata("design:type", Boolean)
|
|
38
|
+
], IndirectCostTemplate.prototype, "isActive", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
(0, typeorm_1.OneToMany)(() => IndirectCostTemplateItem_1.IndirectCostTemplateItem, (item) => item.template, { cascade: true }),
|
|
41
|
+
__metadata("design:type", Array)
|
|
42
|
+
], IndirectCostTemplate.prototype, "items", void 0);
|
|
43
|
+
exports.IndirectCostTemplate = IndirectCostTemplate = __decorate([
|
|
44
|
+
(0, typeorm_1.Entity)("indirect_cost_templates"),
|
|
45
|
+
(0, typeorm_1.Index)(["name"], { unique: true })
|
|
46
|
+
], IndirectCostTemplate);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ObjectLiteral } from "typeorm";
|
|
2
|
+
import { IndirectCostTemplate } from "./IndirectCostTemplate";
|
|
3
|
+
export declare enum IndirectCostCategory {
|
|
4
|
+
ADMIN_CENTRAL = "ADMIN_CENTRAL",
|
|
5
|
+
ADMIN_OBRA = "ADMIN_OBRA",
|
|
6
|
+
VIATICOS_TRANSPORTE = "VIATICOS_TRANSPORTE",
|
|
7
|
+
HERRAMIENTAS_EQUIPO = "HERRAMIENTAS_EQUIPO",
|
|
8
|
+
SEGUROS_FIANZAS = "SEGUROS_FIANZAS",
|
|
9
|
+
IMPREVISTOS = "IMPREVISTOS"
|
|
10
|
+
}
|
|
11
|
+
export declare class IndirectCostTemplateItem implements ObjectLiteral {
|
|
12
|
+
idIndirectCostTemplateItem: number;
|
|
13
|
+
template: IndirectCostTemplate;
|
|
14
|
+
category: IndirectCostCategory;
|
|
15
|
+
name: string;
|
|
16
|
+
description?: string | null;
|
|
17
|
+
percentage: number;
|
|
18
|
+
sortOrder: number;
|
|
19
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.IndirectCostTemplateItem = exports.IndirectCostCategory = void 0;
|
|
13
|
+
// apu/entities/IndirectCostTemplateItem.ts
|
|
14
|
+
const typeorm_1 = require("typeorm");
|
|
15
|
+
const IndirectCostTemplate_1 = require("./IndirectCostTemplate");
|
|
16
|
+
var IndirectCostCategory;
|
|
17
|
+
(function (IndirectCostCategory) {
|
|
18
|
+
IndirectCostCategory["ADMIN_CENTRAL"] = "ADMIN_CENTRAL";
|
|
19
|
+
IndirectCostCategory["ADMIN_OBRA"] = "ADMIN_OBRA";
|
|
20
|
+
IndirectCostCategory["VIATICOS_TRANSPORTE"] = "VIATICOS_TRANSPORTE";
|
|
21
|
+
IndirectCostCategory["HERRAMIENTAS_EQUIPO"] = "HERRAMIENTAS_EQUIPO";
|
|
22
|
+
IndirectCostCategory["SEGUROS_FIANZAS"] = "SEGUROS_FIANZAS";
|
|
23
|
+
IndirectCostCategory["IMPREVISTOS"] = "IMPREVISTOS";
|
|
24
|
+
})(IndirectCostCategory || (exports.IndirectCostCategory = IndirectCostCategory = {}));
|
|
25
|
+
let IndirectCostTemplateItem = class IndirectCostTemplateItem {
|
|
26
|
+
};
|
|
27
|
+
exports.IndirectCostTemplateItem = IndirectCostTemplateItem;
|
|
28
|
+
__decorate([
|
|
29
|
+
(0, typeorm_1.PrimaryGeneratedColumn)("increment"),
|
|
30
|
+
__metadata("design:type", Number)
|
|
31
|
+
], IndirectCostTemplateItem.prototype, "idIndirectCostTemplateItem", void 0);
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, typeorm_1.ManyToOne)(() => IndirectCostTemplate_1.IndirectCostTemplate, { nullable: false, onDelete: "CASCADE" }),
|
|
34
|
+
(0, typeorm_1.JoinColumn)({ name: "idIndirectCostTemplate" }),
|
|
35
|
+
__metadata("design:type", IndirectCostTemplate_1.IndirectCostTemplate)
|
|
36
|
+
], IndirectCostTemplateItem.prototype, "template", void 0);
|
|
37
|
+
__decorate([
|
|
38
|
+
(0, typeorm_1.Column)({
|
|
39
|
+
type: "enum",
|
|
40
|
+
enum: IndirectCostCategory
|
|
41
|
+
}),
|
|
42
|
+
__metadata("design:type", String)
|
|
43
|
+
], IndirectCostTemplateItem.prototype, "category", void 0);
|
|
44
|
+
__decorate([
|
|
45
|
+
(0, typeorm_1.Column)("varchar", { length: 255 }),
|
|
46
|
+
__metadata("design:type", String)
|
|
47
|
+
], IndirectCostTemplateItem.prototype, "name", void 0);
|
|
48
|
+
__decorate([
|
|
49
|
+
(0, typeorm_1.Column)("text", { nullable: true }),
|
|
50
|
+
__metadata("design:type", Object)
|
|
51
|
+
], IndirectCostTemplateItem.prototype, "description", void 0);
|
|
52
|
+
__decorate([
|
|
53
|
+
(0, typeorm_1.Column)("decimal", { precision: 5, scale: 4, default: 0 }),
|
|
54
|
+
__metadata("design:type", Number)
|
|
55
|
+
], IndirectCostTemplateItem.prototype, "percentage", void 0);
|
|
56
|
+
__decorate([
|
|
57
|
+
(0, typeorm_1.Column)("int", { default: 0 }),
|
|
58
|
+
__metadata("design:type", Number)
|
|
59
|
+
], IndirectCostTemplateItem.prototype, "sortOrder", void 0);
|
|
60
|
+
exports.IndirectCostTemplateItem = IndirectCostTemplateItem = __decorate([
|
|
61
|
+
(0, typeorm_1.Entity)("indirect_cost_template_items"),
|
|
62
|
+
(0, typeorm_1.Index)(["template", "category"], { unique: true }),
|
|
63
|
+
(0, typeorm_1.Check)(`"percentage" >= 0 AND "percentage" <= 1`)
|
|
64
|
+
], IndirectCostTemplateItem);
|
|
@@ -12,3 +12,9 @@ export { Resource } from './Resource';
|
|
|
12
12
|
export { ResourcePrice } from './ResourcePrice';
|
|
13
13
|
export { ResourceType } from './enums/resource-type.enum';
|
|
14
14
|
export { BudgetSnapshot } from './budget-snapshot.entity';
|
|
15
|
+
export { IndirectCostTemplate } from './IndirectCostTemplate';
|
|
16
|
+
export { IndirectCostTemplateItem, IndirectCostCategory } from './IndirectCostTemplateItem';
|
|
17
|
+
export { IndirectCostConfig, IndirectCostScope } from './IndirectCostConfig';
|
|
18
|
+
export { IndirectCostItem } from './IndirectCostItem';
|
|
19
|
+
export { IndirectCostCalculator } from './IndirectCostCalculator';
|
|
20
|
+
export { ConceptCategory } from './Concept';
|
package/dist/models/apu/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BudgetSnapshot = exports.ResourceType = exports.ResourcePrice = exports.Resource = exports.Project = exports.PriceList = exports.Concept = exports.Company = exports.Client = exports.BudgetCancellationFolio = exports.BudgetItem = exports.Budget = exports.ApuItem = exports.Apu = void 0;
|
|
3
|
+
exports.ConceptCategory = exports.IndirectCostCalculator = exports.IndirectCostItem = exports.IndirectCostScope = exports.IndirectCostConfig = exports.IndirectCostCategory = exports.IndirectCostTemplateItem = exports.IndirectCostTemplate = exports.BudgetSnapshot = exports.ResourceType = exports.ResourcePrice = exports.Resource = exports.Project = exports.PriceList = exports.Concept = exports.Company = exports.Client = exports.BudgetCancellationFolio = exports.BudgetItem = exports.Budget = exports.ApuItem = exports.Apu = void 0;
|
|
4
4
|
var Apu_1 = require("./Apu"); //
|
|
5
5
|
Object.defineProperty(exports, "Apu", { enumerable: true, get: function () { return Apu_1.Apu; } });
|
|
6
6
|
var ApuItem_1 = require("./ApuItem"); //
|
|
@@ -29,3 +29,19 @@ var resource_type_enum_1 = require("./enums/resource-type.enum");
|
|
|
29
29
|
Object.defineProperty(exports, "ResourceType", { enumerable: true, get: function () { return resource_type_enum_1.ResourceType; } });
|
|
30
30
|
var budget_snapshot_entity_1 = require("./budget-snapshot.entity");
|
|
31
31
|
Object.defineProperty(exports, "BudgetSnapshot", { enumerable: true, get: function () { return budget_snapshot_entity_1.BudgetSnapshot; } });
|
|
32
|
+
// Indirect Cost System
|
|
33
|
+
var IndirectCostTemplate_1 = require("./IndirectCostTemplate");
|
|
34
|
+
Object.defineProperty(exports, "IndirectCostTemplate", { enumerable: true, get: function () { return IndirectCostTemplate_1.IndirectCostTemplate; } });
|
|
35
|
+
var IndirectCostTemplateItem_1 = require("./IndirectCostTemplateItem");
|
|
36
|
+
Object.defineProperty(exports, "IndirectCostTemplateItem", { enumerable: true, get: function () { return IndirectCostTemplateItem_1.IndirectCostTemplateItem; } });
|
|
37
|
+
Object.defineProperty(exports, "IndirectCostCategory", { enumerable: true, get: function () { return IndirectCostTemplateItem_1.IndirectCostCategory; } });
|
|
38
|
+
var IndirectCostConfig_1 = require("./IndirectCostConfig");
|
|
39
|
+
Object.defineProperty(exports, "IndirectCostConfig", { enumerable: true, get: function () { return IndirectCostConfig_1.IndirectCostConfig; } });
|
|
40
|
+
Object.defineProperty(exports, "IndirectCostScope", { enumerable: true, get: function () { return IndirectCostConfig_1.IndirectCostScope; } });
|
|
41
|
+
var IndirectCostItem_1 = require("./IndirectCostItem");
|
|
42
|
+
Object.defineProperty(exports, "IndirectCostItem", { enumerable: true, get: function () { return IndirectCostItem_1.IndirectCostItem; } });
|
|
43
|
+
var IndirectCostCalculator_1 = require("./IndirectCostCalculator");
|
|
44
|
+
Object.defineProperty(exports, "IndirectCostCalculator", { enumerable: true, get: function () { return IndirectCostCalculator_1.IndirectCostCalculator; } });
|
|
45
|
+
// Export ConceptCategory enum
|
|
46
|
+
var Concept_2 = require("./Concept");
|
|
47
|
+
Object.defineProperty(exports, "ConceptCategory", { enumerable: true, get: function () { return Concept_2.ConceptCategory; } });
|
package/package.json
CHANGED
package/src/models/apu/Apu.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
} from "typeorm";
|
|
4
4
|
import { Concept } from "./Concept";
|
|
5
5
|
import { ApuItem } from "./ApuItem";
|
|
6
|
+
import { IndirectCostConfig } from "./IndirectCostConfig";
|
|
6
7
|
|
|
7
8
|
@Entity("apu")
|
|
8
9
|
@Unique("uq_apu_concept_version", ["concept", "version"])
|
|
@@ -37,4 +38,7 @@ export class Apu implements ObjectLiteral {
|
|
|
37
38
|
|
|
38
39
|
@OneToMany(() => ApuItem, (ai) => ai.apu, { cascade: true })
|
|
39
40
|
items?: ApuItem[];
|
|
41
|
+
|
|
42
|
+
@OneToMany(() => IndirectCostConfig, (config) => config.apu)
|
|
43
|
+
indirectCostConfig?: IndirectCostConfig;
|
|
40
44
|
}
|
|
@@ -6,6 +6,19 @@ import { UnitOfMeasure } from "../../entities/UnitOfMesure"; // <-- ajusta tu ru
|
|
|
6
6
|
import { Apu } from "./Apu";
|
|
7
7
|
import { BudgetItem } from "./BudgetItem";
|
|
8
8
|
|
|
9
|
+
export enum ConceptCategory {
|
|
10
|
+
JARDINERIA = "JAR",
|
|
11
|
+
RIEGO = "RIE",
|
|
12
|
+
OBRAS_CIVILES = "OBR",
|
|
13
|
+
MOBILIARIO = "MOB",
|
|
14
|
+
TERRACERIAS = "TER",
|
|
15
|
+
MANTENIMIENTO = "MAN",
|
|
16
|
+
MATERIALES = "MAT",
|
|
17
|
+
MANO_DE_OBRA = "LAB",
|
|
18
|
+
HERRAMIENTAS = "TOOL",
|
|
19
|
+
FERTILIZACION = "FER"
|
|
20
|
+
}
|
|
21
|
+
|
|
9
22
|
@Entity("concepts")
|
|
10
23
|
@Index(["code"], { unique: true })
|
|
11
24
|
export class Concept implements ObjectLiteral {
|
|
@@ -31,8 +44,12 @@ export class Concept implements ObjectLiteral {
|
|
|
31
44
|
@Column("varchar", { length: 64, nullable: true })
|
|
32
45
|
satUnit?: string | null;
|
|
33
46
|
|
|
34
|
-
@Column(
|
|
35
|
-
|
|
47
|
+
@Column({
|
|
48
|
+
type: "enum",
|
|
49
|
+
enum: ConceptCategory,
|
|
50
|
+
nullable: true
|
|
51
|
+
})
|
|
52
|
+
category?: ConceptCategory | null;
|
|
36
53
|
|
|
37
54
|
@Column({ type: "boolean", default: true })
|
|
38
55
|
isActive!: boolean;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// apu/utils/IndirectCostCalculator.ts
|
|
2
|
+
import { IndirectCostConfig } from "./IndirectCostConfig";
|
|
3
|
+
|
|
4
|
+
export class IndirectCostCalculator {
|
|
5
|
+
/**
|
|
6
|
+
* Calcula el factor total de costos indirectos para una configuración
|
|
7
|
+
* @param config Configuración de costos indirectos
|
|
8
|
+
* @returns Factor total (0..1)
|
|
9
|
+
*/
|
|
10
|
+
static calculateTotalIndirectFactor(config: IndirectCostConfig): number {
|
|
11
|
+
if (!config.items || config.items.length === 0) {
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return config.items
|
|
16
|
+
.filter(item => item.isActive)
|
|
17
|
+
.reduce((total, item) => total + item.percentage, 0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Calcula el desglose de costos indirectos por categoría
|
|
22
|
+
* @param config Configuración de costos indirectos
|
|
23
|
+
* @param directCost Costo directo base
|
|
24
|
+
* @returns Desglose por categoría
|
|
25
|
+
*/
|
|
26
|
+
static calculateIndirectCostBreakdown(
|
|
27
|
+
config: IndirectCostConfig,
|
|
28
|
+
directCost: number
|
|
29
|
+
): { [category: string]: { percentage: number; amount: number; name: string } } {
|
|
30
|
+
const breakdown: { [category: string]: { percentage: number; amount: number; name: string } } = {};
|
|
31
|
+
|
|
32
|
+
if (!config.items) {
|
|
33
|
+
return breakdown;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
config.items
|
|
37
|
+
.filter(item => item.isActive)
|
|
38
|
+
.forEach(item => {
|
|
39
|
+
breakdown[item.category] = {
|
|
40
|
+
percentage: item.percentage,
|
|
41
|
+
amount: directCost * item.percentage + (item.fixedAmount || 0),
|
|
42
|
+
name: item.name
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return breakdown;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Calcula el costo total incluyendo indirectos
|
|
51
|
+
* @param directCost Costo directo
|
|
52
|
+
* @param config Configuración de costos indirectos
|
|
53
|
+
* @returns Costo total
|
|
54
|
+
*/
|
|
55
|
+
static calculateTotalCost(directCost: number, config: IndirectCostConfig): number {
|
|
56
|
+
const indirectFactor = this.calculateTotalIndirectFactor(config);
|
|
57
|
+
const indirectCost = directCost * indirectFactor;
|
|
58
|
+
|
|
59
|
+
// Agregar montos fijos si existen
|
|
60
|
+
const fixedAmounts = config.items
|
|
61
|
+
?.filter(item => item.isActive && item.fixedAmount)
|
|
62
|
+
.reduce((sum, item) => sum + (item.fixedAmount || 0), 0) || 0;
|
|
63
|
+
|
|
64
|
+
return directCost + indirectCost + fixedAmounts;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Crea una configuración de costos indirectos desde una plantilla
|
|
69
|
+
* @param template Plantilla base
|
|
70
|
+
* @param scope Ámbito de aplicación (APU o PROJECT)
|
|
71
|
+
* @returns Configuración de costos indirectos
|
|
72
|
+
*/
|
|
73
|
+
static createConfigFromTemplate(
|
|
74
|
+
template: any, // IndirectCostTemplate
|
|
75
|
+
scope: "APU" | "PROJECT"
|
|
76
|
+
): Partial<IndirectCostConfig> {
|
|
77
|
+
return {
|
|
78
|
+
scope: scope as any,
|
|
79
|
+
template: template,
|
|
80
|
+
name: `Config basada en ${template.name}`,
|
|
81
|
+
description: template.description,
|
|
82
|
+
items: template.items?.map((templateItem: any) => ({
|
|
83
|
+
category: templateItem.category,
|
|
84
|
+
name: templateItem.name,
|
|
85
|
+
description: templateItem.description,
|
|
86
|
+
percentage: templateItem.percentage,
|
|
87
|
+
sortOrder: templateItem.sortOrder,
|
|
88
|
+
isActive: true
|
|
89
|
+
}))
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// apu/entities/IndirectCostConfig.ts
|
|
2
|
+
import {
|
|
3
|
+
Entity, PrimaryGeneratedColumn, Column, ObjectLiteral, ManyToOne, OneToMany, JoinColumn, Index,
|
|
4
|
+
} from "typeorm";
|
|
5
|
+
import { Apu } from "./Apu";
|
|
6
|
+
import { Project } from "./Project";
|
|
7
|
+
import { IndirectCostTemplate } from "./IndirectCostTemplate";
|
|
8
|
+
import { IndirectCostItem } from "./IndirectCostItem";
|
|
9
|
+
|
|
10
|
+
export enum IndirectCostScope {
|
|
11
|
+
APU = "APU", // Aplica solo a un APU específico
|
|
12
|
+
PROJECT = "PROJECT" // Aplica a todo el proyecto
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@Entity("indirect_cost_configs")
|
|
16
|
+
@Index(["apu"], { unique: true, where: "scope = 'APU'" })
|
|
17
|
+
@Index(["project"], { unique: true, where: "scope = 'PROJECT'" })
|
|
18
|
+
export class IndirectCostConfig implements ObjectLiteral {
|
|
19
|
+
@PrimaryGeneratedColumn("increment")
|
|
20
|
+
idIndirectCostConfig!: number;
|
|
21
|
+
|
|
22
|
+
@Column({
|
|
23
|
+
type: "enum",
|
|
24
|
+
enum: IndirectCostScope
|
|
25
|
+
})
|
|
26
|
+
scope!: IndirectCostScope;
|
|
27
|
+
|
|
28
|
+
@ManyToOne(() => Apu, { nullable: true, onDelete: "CASCADE" })
|
|
29
|
+
@JoinColumn({ name: "idApu" })
|
|
30
|
+
apu?: Apu | null;
|
|
31
|
+
|
|
32
|
+
@ManyToOne(() => Project, { nullable: true, onDelete: "CASCADE" })
|
|
33
|
+
@JoinColumn({ name: "idProject" })
|
|
34
|
+
project?: Project | null;
|
|
35
|
+
|
|
36
|
+
@ManyToOne(() => IndirectCostTemplate, { nullable: true })
|
|
37
|
+
@JoinColumn({ name: "idIndirectCostTemplate" })
|
|
38
|
+
template?: IndirectCostTemplate | null;
|
|
39
|
+
|
|
40
|
+
@Column("varchar", { length: 255, nullable: true })
|
|
41
|
+
name?: string | null;
|
|
42
|
+
|
|
43
|
+
@Column("text", { nullable: true })
|
|
44
|
+
description?: string | null;
|
|
45
|
+
|
|
46
|
+
@OneToMany(() => IndirectCostItem, (item) => item.config, { cascade: true })
|
|
47
|
+
items?: IndirectCostItem[];
|
|
48
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// apu/entities/IndirectCostItem.ts
|
|
2
|
+
import {
|
|
3
|
+
Entity, PrimaryGeneratedColumn, Column, ObjectLiteral, ManyToOne, JoinColumn, Index, Check,
|
|
4
|
+
} from "typeorm";
|
|
5
|
+
import { IndirectCostConfig } from "./IndirectCostConfig";
|
|
6
|
+
import { IndirectCostCategory } from "./IndirectCostTemplateItem";
|
|
7
|
+
|
|
8
|
+
@Entity("indirect_cost_items")
|
|
9
|
+
@Index(["config", "category"], { unique: true })
|
|
10
|
+
@Check(`"percentage" >= 0 AND "percentage" <= 1`)
|
|
11
|
+
export class IndirectCostItem implements ObjectLiteral {
|
|
12
|
+
@PrimaryGeneratedColumn("increment")
|
|
13
|
+
idIndirectCostItem!: number;
|
|
14
|
+
|
|
15
|
+
@ManyToOne(() => IndirectCostConfig, { nullable: false, onDelete: "CASCADE" })
|
|
16
|
+
@JoinColumn({ name: "idIndirectCostConfig" })
|
|
17
|
+
config!: IndirectCostConfig;
|
|
18
|
+
|
|
19
|
+
@Column({
|
|
20
|
+
type: "enum",
|
|
21
|
+
enum: IndirectCostCategory
|
|
22
|
+
})
|
|
23
|
+
category!: IndirectCostCategory;
|
|
24
|
+
|
|
25
|
+
@Column("varchar", { length: 255 })
|
|
26
|
+
name!: string;
|
|
27
|
+
|
|
28
|
+
@Column("text", { nullable: true })
|
|
29
|
+
description?: string | null;
|
|
30
|
+
|
|
31
|
+
@Column("decimal", { precision: 5, scale: 4, default: 0 })
|
|
32
|
+
percentage!: number; // 0..1 (porcentaje sobre costo directo)
|
|
33
|
+
|
|
34
|
+
@Column("decimal", { precision: 18, scale: 2, nullable: true })
|
|
35
|
+
fixedAmount?: number | null; // Monto fijo opcional
|
|
36
|
+
|
|
37
|
+
@Column("int", { default: 0 })
|
|
38
|
+
sortOrder!: number;
|
|
39
|
+
|
|
40
|
+
@Column({ type: "boolean", default: true })
|
|
41
|
+
isActive!: boolean;
|
|
42
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// apu/entities/IndirectCostTemplate.ts
|
|
2
|
+
import {
|
|
3
|
+
Entity, PrimaryGeneratedColumn, Column, ObjectLiteral, OneToMany, Index,
|
|
4
|
+
} from "typeorm";
|
|
5
|
+
import { IndirectCostTemplateItem } from "./IndirectCostTemplateItem";
|
|
6
|
+
|
|
7
|
+
@Entity("indirect_cost_templates")
|
|
8
|
+
@Index(["name"], { unique: true })
|
|
9
|
+
export class IndirectCostTemplate implements ObjectLiteral {
|
|
10
|
+
@PrimaryGeneratedColumn("increment")
|
|
11
|
+
idIndirectCostTemplate!: number;
|
|
12
|
+
|
|
13
|
+
@Column("varchar", { length: 255, unique: true })
|
|
14
|
+
name!: string;
|
|
15
|
+
|
|
16
|
+
@Column("text", { nullable: true })
|
|
17
|
+
description?: string | null;
|
|
18
|
+
|
|
19
|
+
@Column("varchar", { length: 64, nullable: true })
|
|
20
|
+
projectType?: string | null; // Tipo de obra: "JARDINERIA", "RIEGO", etc.
|
|
21
|
+
|
|
22
|
+
@Column({ type: "boolean", default: true })
|
|
23
|
+
isActive!: boolean;
|
|
24
|
+
|
|
25
|
+
@OneToMany(() => IndirectCostTemplateItem, (item) => item.template, { cascade: true })
|
|
26
|
+
items?: IndirectCostTemplateItem[];
|
|
27
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// apu/entities/IndirectCostTemplateItem.ts
|
|
2
|
+
import {
|
|
3
|
+
Entity, PrimaryGeneratedColumn, Column, ObjectLiteral, ManyToOne, JoinColumn, Index, Check,
|
|
4
|
+
} from "typeorm";
|
|
5
|
+
import { IndirectCostTemplate } from "./IndirectCostTemplate";
|
|
6
|
+
|
|
7
|
+
export enum IndirectCostCategory {
|
|
8
|
+
ADMIN_CENTRAL = "ADMIN_CENTRAL",
|
|
9
|
+
ADMIN_OBRA = "ADMIN_OBRA",
|
|
10
|
+
VIATICOS_TRANSPORTE = "VIATICOS_TRANSPORTE",
|
|
11
|
+
HERRAMIENTAS_EQUIPO = "HERRAMIENTAS_EQUIPO",
|
|
12
|
+
SEGUROS_FIANZAS = "SEGUROS_FIANZAS",
|
|
13
|
+
IMPREVISTOS = "IMPREVISTOS"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@Entity("indirect_cost_template_items")
|
|
17
|
+
@Index(["template", "category"], { unique: true })
|
|
18
|
+
@Check(`"percentage" >= 0 AND "percentage" <= 1`)
|
|
19
|
+
export class IndirectCostTemplateItem implements ObjectLiteral {
|
|
20
|
+
@PrimaryGeneratedColumn("increment")
|
|
21
|
+
idIndirectCostTemplateItem!: number;
|
|
22
|
+
|
|
23
|
+
@ManyToOne(() => IndirectCostTemplate, { nullable: false, onDelete: "CASCADE" })
|
|
24
|
+
@JoinColumn({ name: "idIndirectCostTemplate" })
|
|
25
|
+
template!: IndirectCostTemplate;
|
|
26
|
+
|
|
27
|
+
@Column({
|
|
28
|
+
type: "enum",
|
|
29
|
+
enum: IndirectCostCategory
|
|
30
|
+
})
|
|
31
|
+
category!: IndirectCostCategory;
|
|
32
|
+
|
|
33
|
+
@Column("varchar", { length: 255 })
|
|
34
|
+
name!: string;
|
|
35
|
+
|
|
36
|
+
@Column("text", { nullable: true })
|
|
37
|
+
description?: string | null;
|
|
38
|
+
|
|
39
|
+
@Column("decimal", { precision: 5, scale: 4, default: 0 })
|
|
40
|
+
percentage!: number; // 0..1 (porcentaje sobre costo directo)
|
|
41
|
+
|
|
42
|
+
@Column("int", { default: 0 })
|
|
43
|
+
sortOrder!: number;
|
|
44
|
+
}
|
package/src/models/apu/index.ts
CHANGED
|
@@ -11,4 +11,14 @@ export { Project } from './Project';
|
|
|
11
11
|
export { Resource } from './Resource'; //
|
|
12
12
|
export { ResourcePrice } from './ResourcePrice'; //
|
|
13
13
|
export { ResourceType } from './enums/resource-type.enum';
|
|
14
|
-
export { BudgetSnapshot } from './budget-snapshot.entity'
|
|
14
|
+
export { BudgetSnapshot } from './budget-snapshot.entity';
|
|
15
|
+
|
|
16
|
+
// Indirect Cost System
|
|
17
|
+
export { IndirectCostTemplate } from './IndirectCostTemplate';
|
|
18
|
+
export { IndirectCostTemplateItem, IndirectCostCategory } from './IndirectCostTemplateItem';
|
|
19
|
+
export { IndirectCostConfig, IndirectCostScope } from './IndirectCostConfig';
|
|
20
|
+
export { IndirectCostItem } from './IndirectCostItem';
|
|
21
|
+
export { IndirectCostCalculator } from './IndirectCostCalculator';
|
|
22
|
+
|
|
23
|
+
// Export ConceptCategory enum
|
|
24
|
+
export { ConceptCategory } from './Concept';
|