Add field management module with database schema and validation

- Introduced `FieldModule` to manage cycles and plans, including read and write controllers.
- Created database migrations for `company_settings`, `cycles`, `cycle_weekdays`, `cycle_destinations`, `plans`, `plan_destinations`, `plan_invoices`, and `plan_packing_slips` tables, including constraints and unique indexes.
- Developed service and repository layers for handling cycle and plan data operations.
- Added unit tests for the cycles and plans services, repositories, and controllers to ensure functionality and correctness.
- Updated application module to include the new `FieldModule` for better organization.
This commit is contained in:
shancheas
2026-08-25 18:20:19 +07:00
parent 34d4f2c120
commit c9f9b31abf
53 changed files with 5990 additions and 5 deletions
@@ -0,0 +1,67 @@
import {
BadRequestException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { InvalidDateTimeError } from '../../../common/value-objects/date-time/invalid-date-time.error';
import { DateTime } from '../../../common/value-objects/date-time/date-time';
import { CompanySettingsRepository } from './company-settings.repository';
import type { CompanySetting } from './company-setting';
@Injectable()
export class CompanySettingsService {
constructor(
private readonly companySettingsRepository: CompanySettingsRepository,
) {}
async get(): Promise<ReturnType<CompanySettingsService['toItem']>> {
const setting = await this.companySettingsRepository.find();
if (!setting) {
throw new NotFoundException('Settings not configured');
}
return this.toItem(setting);
}
async update(
cycleStartDateRaw: string,
userId: string,
): Promise<ReturnType<CompanySettingsService['toItem']>> {
const cycleStartDate = this.assertDate(cycleStartDateRaw).startOfDay();
const saved = await this.companySettingsRepository.upsert({
cycleStartDate,
userId,
});
return this.toItem(saved);
}
async requireCycleStartDate(): Promise<DateTime> {
const setting = await this.companySettingsRepository.find();
if (!setting) {
throw new NotFoundException('Settings not configured');
}
return setting.cycleStartDate;
}
toItem(setting: CompanySetting) {
return {
id: setting.id,
cycleStartDate: setting.cycleStartDate.value,
status: setting.status.value,
createdAt: setting.createdAt.value,
updatedAt: setting.updatedAt.value,
createdBy: setting.createdBy,
updatedBy: setting.updatedBy,
};
}
private assertDate(raw: string): DateTime {
try {
return DateTime.create(raw);
} catch (error) {
if (error instanceof InvalidDateTimeError) {
throw new BadRequestException('Invalid cycle start date');
}
throw error;
}
}
}