| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- /**
- * * **Current State:** `BlockService` imports and initializes `PhaseRepository` to perform cross-entity validation checking if a `Phase` exists before creating or updating a `Block`.
- * * **Intended Mutation:** Remove `PhaseRepository` from imports, properties, `getRepos()`, `create()`, and `update()` methods to unbind Phase and Block entities.
- * * **Risk Mitigation:** Cross-entity validation is entirely shifted to the `FFB Production` ledger level, making the master block seeder 100% independent.
- */
- import { Injectable, NotFoundException, Inject, forwardRef } from '@nestjs/common';
- import { FFBLangChainService } from '../../FFB/services/ffb-langchain.service';
- import { MongoCoreService } from '../../mongo/mongo-core.service';
- import { BlockRepository } from '../repositories/block.repository';
- import { Block } from '../schemas/site.schema';
- import { FFBProductionService } from '../../FFB/services/ffb-production.service';
- @Injectable()
- export class BlockService {
- private repo: BlockRepository;
- constructor(
- private readonly mongoCore: MongoCoreService,
- @Inject(forwardRef(() => FFBProductionService))
- private readonly ffbService: FFBProductionService,
- @Inject(forwardRef(() => FFBLangChainService))
- private readonly ffbLangChainService: FFBLangChainService,
- ) { }
- private async getRepos() {
- if (!this.repo) {
- const db = await this.mongoCore.getDb();
- this.repo = new BlockRepository(db);
- await this.repo.init();
- }
- return { repo: this.repo };
- }
- async create(block: Block): Promise<Block> {
- const { repo } = await this.getRepos();
- return repo.create(block);
- }
- async findAll(filter: Record<string, any> = {}): Promise<Block[]> {
- const { repo } = await this.getRepos();
- return repo.findAll(filter);
- }
- async findById(id: string): Promise<Block | null> {
- const { repo } = await this.getRepos();
- return repo.findById(id);
- }
- async update(id: string, update: Partial<Block>): Promise<void> {
- const { repo } = await this.getRepos();
- const block = await repo.findById(id);
- if (!block) throw new NotFoundException('Block not found');
- await repo.update(id, update);
- }
- async delete(id: string): Promise<void> {
- const { repo } = await this.getRepos();
- const block = await repo.findById(id);
- if (!block) throw new NotFoundException('Block not found');
- // Cascading Delete:
- // 1. Delete all FFB Production records referencing this block
- await this.ffbService.deleteMany({ blockCode: block.blockCode });
- // 2. Delete the block itself
- await repo.delete(id);
- }
- async generateDescription(data: { name: string, phaseName?: string, size?: number, numOfTrees?: number }): Promise<{ description: string }> {
- const prompt = `Write a realistic, professional description (2–4 sentences) for an oil palm plantation block named "${data.name}"${data.phaseName ? ` within phase "${data.phaseName}"` : ''}.${data.size ? ` It has a size of ${data.size} units` : ''}${data.numOfTrees ? ` and contains ${data.numOfTrees} trees` : ''}.
- Choose 1-2 aspects from the following to incorporate naturally:
- - Block health and maturity (e.g., trees at peak production age, healthy canopy development, consistent fruit set)
- - Field accessibility (e.g., easily accessible by tractor paths, slightly sloped area requiring specialized harvesting tools)
- - Environmental features (e.g., bordering primary forest, presence of natural irrigation channels, rich nutrient-holding soil)
- - Monitoring and care (e.g., subject to intensive pest monitoring, recently fertilized, under strict irrigation schedule)
- Guidelines:
- - Maintain a grounded, operational tone.
- - Do not mention the bullet points explicitly; weave them into the narrative.
- - Ensure the length is exactly 2-4 sentences.
- Description:`;
- const description = await this.ffbLangChainService.chatStateless(prompt);
- return { description: description.replace(/^Description:\s*/i, '').trim() };
- }
- }
|