Add address fields to sales invoices and implement related validations

- Introduced new columns `address`, `latitude`, and `longitude` in the `sales_invoices` table to store location details.
- Updated the `SalesInvoicesService` to handle the new fields, including validation for address format and geographical coordinates.
- Enhanced the `SalesInvoiceDto` and related data transfer objects to include the new fields for API requests and responses.
- Added unit and e2e tests to ensure proper handling of the new fields and validate their integration within the sales invoice workflow.
- Created a new migration script to apply the database schema changes for the sales invoices.
This commit is contained in:
shancheas
2026-09-01 09:50:19 +07:00
parent 23028abd48
commit 0e73d14381
23 changed files with 444 additions and 33 deletions
+23 -5
View File
@@ -14,6 +14,23 @@ import {
} from '../src/database/schema';
import { PRIVILEGE_ACTIONS } from '../src/modules/privileges/privilege-action';
import { registerAndActivate } from './helpers/activate-user';
import { DateTime } from '../src/common/value-objects/date-time/date-time';
const MS_PER_DAY = 86_400_000;
function nextMondayRange(): { from: string; to: string } {
const start = DateTime.fromUnixMs(Math.trunc(Date.now())).startOfDay();
const mondays: string[] = [];
for (let offset = 0; offset < 21 && mondays.length < 2; offset += 1) {
const day = DateTime.fromUnixMs(
start.value + offset * MS_PER_DAY,
).startOfDay();
if (day.weekdayName() === 'monday') {
mondays.push(day.format().slice(0, 10));
}
}
return { from: mondays[0], to: mondays[1] };
}
describe('Plans (e2e)', () => {
let app: INestApplication<App>;
@@ -203,14 +220,15 @@ describe('Plans (e2e)', () => {
});
it('generates Monday plans, skips existing, and supports D-Day destination edits', async () => {
const { from, to } = nextMondayRange();
const generated = await request(app.getHttpServer())
.post('/plans/generate')
.set('Authorization', `Bearer ${adminAccessToken}`)
.send({
employeeId,
purpose: 'sales',
from: '2026-01-05',
to: '2026-01-12',
from,
to,
})
.expect(201);
expect((generated.body as { created: number }).created).toBe(2);
@@ -222,15 +240,15 @@ describe('Plans (e2e)', () => {
.send({
employeeId,
purpose: 'sales',
from: '2026-01-05',
to: '2026-01-12',
from,
to,
})
.expect(201);
expect((again.body as { created: number }).created).toBe(0);
const list = await request(app.getHttpServer())
.get('/plans')
.query({ employeeId, purpose: 'sales', date: '2026-01-05' })
.query({ employeeId, purpose: 'sales', date: from })
.set('Authorization', `Bearer ${adminAccessToken}`)
.expect(200);
const planId = (list.body.data as Array<{ id: string }>)[0].id;