fix publication details

This commit is contained in:
peter.maquiran
2025-09-11 11:20:44 +01:00
parent 69e4334ebf
commit 5f7295d41c
74 changed files with 1639 additions and 678 deletions
+47
View File
@@ -0,0 +1,47 @@
import { BaseEntity } from "src/app/utils/entity";
import { z } from "zod"
export const ActionEntitySchema = z.object({
processId: z.number(),
applicationId: z.number(),
organicEntityId: z.number(),
securityId: z.number(),
serieId: z.number(),
userId: z.number(),
dateIndex: z.string().datetime(), // ISO 8601 datetime
description: z.string(),
detail: z.string(),
dateBegin: z.string().datetime(),
dateEnd: z.string().datetime(),
actionType: z.number(),
location: z.string(),
isExported: z.boolean(),
sourceLocation: z.number(),
sourceProcessId: z.number(),
})
export type IAction = z.infer<typeof ActionEntitySchema>
export class ActionEntity extends BaseEntity<ActionEntity>(ActionEntitySchema) implements IAction{
processId: typeof ActionEntitySchema._input.processId
applicationId: typeof ActionEntitySchema._input.processId
organicEntityId: typeof ActionEntitySchema._input.processId
securityId: typeof ActionEntitySchema._input.processId
serieId: typeof ActionEntitySchema._input.processId
userId: typeof ActionEntitySchema._input.processId
dateIndex: typeof ActionEntitySchema._input.dateIndex
description: typeof ActionEntitySchema._input.description
detail: typeof ActionEntitySchema._input.detail
dateBegin: typeof ActionEntitySchema._input.dateBegin
dateEnd: typeof ActionEntitySchema._input.dateEnd
actionType: typeof ActionEntitySchema._input.processId
location: typeof ActionEntitySchema._input.location
isExported: typeof ActionEntitySchema._input.isExported
sourceLocation:typeof ActionEntitySchema._input.processId
sourceProcessId: typeof ActionEntitySchema._input.processId
constructor(data: IAction) {
super();
Object.assign(this, data)
}
}
@@ -0,0 +1,27 @@
import { z } from "zod"
export const PublicationDocumentEntitySchema = z.object({
id: z.number().optional(),
file: z.string(),
extension: z.string(),
name: z.string(),
path: z.string(),
documentId: z.number(),
datePublication: z.string(),
})
export type IPublicationDocument = z.infer<typeof PublicationDocumentEntitySchema>
export class PublicationDocumentEntity implements IPublicationDocument{
file: typeof PublicationDocumentEntitySchema._input.file
extension: typeof PublicationDocumentEntitySchema._input.extension
name: typeof PublicationDocumentEntitySchema._input.name
path: typeof PublicationDocumentEntitySchema._input.path
documentId: typeof PublicationDocumentEntitySchema._input.documentId
datePublication: typeof PublicationDocumentEntitySchema._input.datePublication
id: typeof PublicationDocumentEntitySchema._input.id
constructor(data: IPublicationDocument) {
Object.assign(this, data)
}
}
@@ -0,0 +1,43 @@
import { BaseEntity } from "src/app/utils/entity";
import { z } from "zod"
export const PublicationEntitySchema = z.object({
processId: z.number(),
documentId: z.number(),
applicationId: z.number(),
organicEntityId: z.number(),
securityId: z.number(),
userId: z.number(),
dateIndex: z.string(),
phase: z.number(),
title: z.string(),
message: z.string(),
datePublication: z.string(),
isExported: z.boolean(),
sourceLocation: z.number(),
sourceProcessId: z.number(),
sourceDocumentId: z.number(),
})
export type IPublication = z.infer<typeof PublicationEntitySchema>
export class PublicationEntity extends BaseEntity<PublicationEntity>(PublicationEntitySchema) implements IPublication{
processId: typeof PublicationEntitySchema._input.processId
applicationId: typeof PublicationEntitySchema._input.processId
organicEntityId: typeof PublicationEntitySchema._input.processId
securityId: typeof PublicationEntitySchema._input.processId
serieId: typeof PublicationEntitySchema._input.processId
userId: typeof PublicationEntitySchema._input.processId
dateIndex: typeof PublicationEntitySchema._input.dateIndex
isExported: typeof PublicationEntitySchema._input.isExported
sourceLocation:typeof PublicationEntitySchema._input.processId
sourceProcessId: typeof PublicationEntitySchema._input.processId
sourceDocumentId:typeof PublicationEntitySchema._input.sourceDocumentId
documentId: typeof PublicationEntitySchema._input.documentId
datePublication: typeof PublicationEntitySchema._input.datePublication
constructor(data: IPublication) {
super();
Object.assign(this, data)
}
}
@@ -0,0 +1,36 @@
import { Injectable } from '@angular/core';
import { ActionLocalRepositoryService } from 'src/app/module/actions/data/repository/action-local-repository.service';
import { ActionRemoteRepositoryService } from 'src/app/module/actions/data/repository/action-remote-repository.service';
import { z } from 'zod';
export const ActionsCreateInputDTOSchema = z.object({
userId: z.number(),
description: z.string(),
detail: z.string(),
location: z.string(),
dateBegin: z.string().refine((val) => !isNaN(Date.parse(val)), {
message: "Invalid ISO date string",
}),
dateEnd: z.string().refine((val) => !isNaN(Date.parse(val)), {
message: "Invalid ISO date string",
}),
actionType: z.string(),
});
export type ActionsCreateInput = z.infer<typeof ActionsCreateInputDTOSchema>
@Injectable({
providedIn: 'root'
})
export class ActionsCreateUseCaseService {
constructor(
private remote: ActionRemoteRepositoryService,
private local: ActionLocalRepositoryService
) { }
execute(input: ActionsCreateInput) {
this.remote.create(input);
}
}
@@ -0,0 +1,53 @@
import { Injectable } from '@angular/core';
import { ActionLocalRepositoryService } from 'src/app/module/actions/data/repository/action-local-repository.service';
import { ActionRemoteRepositoryService } from 'src/app/module/actions/data/repository/action-remote-repository.service';
import { z } from "zod";
export const ActionGetAllOutPutSchema = z.array(z.object({
processId: z.number(),
applicationId: z.number(),
organicEntityId: z.number(),
securityId: z.number(),
serieId: z.number(),
userId: z.number(),
dateIndex: z.string().datetime(), // ISO 8601 datetime
description: z.string(),
detail: z.string(),
dateBegin: z.string().datetime(),
dateEnd: z.string().datetime(),
actionType: z.number(),
location: z.string(),
isExported: z.boolean(),
sourceLocation: z.number(),
sourceProcessId: z.number(),
}));
// Example usage:
export type ActionGetAllOutPut = z.infer<typeof ActionGetAllOutPutSchema>;
@Injectable({
providedIn: 'root'
})
export class ActionsGetAllUseCaseService {
constructor(
private remote: ActionRemoteRepositoryService,
private local: ActionLocalRepositoryService
) { }
async execute() {
var result = await this.remote.actionGetAll();
if(result.isOk()) {
const data = result.value.data.data;
this.local.createTransaction( async (table) => {
// Clear the table before inserting new data
await table.clear();
// Insert the new data
await table.bulkAdd(data);
});
}
}
}
@@ -0,0 +1,105 @@
import { Injectable } from '@angular/core';
import { Result } from 'neverthrow';
import { PublicationFileLocalRepositoryService } from 'src/app/module/actions/data/repository/publication-file-local-repository.service';
import { PublicationFileRemoteRepositoryService } from 'src/app/module/actions/data/repository/publication-file-remote-repository.service';
import { z } from 'zod';
import { HttpErrorResponse } from '@angular/common/http';
export const PublicationFileGetByDocumentIdInputDTOSchema = z.object({
datePublication: z.string(),
documentId: z.number(),
processId: z.number(),
});
export type PublicationFileGetByDocumentIdInput = z.infer<typeof PublicationFileGetByDocumentIdInputDTOSchema>
export const PublicationFileGetByDocumentIdOutPutDTOSchema = z.object({
id: z.number().optional(),
file: z.string(),
extension: z.string(),
name: z.string(),
path: z.string(),
documentId: z.number(),
datePublication: z.string(),
}).array();
export type PublicationFileGetByDocumentIdOutPut = z.infer<typeof PublicationFileGetByDocumentIdOutPutDTOSchema>
export interface IPublicationFilesSyncResult {
added: PublicationFileGetByDocumentIdOutPut;
updated: PublicationFileGetByDocumentIdOutPut;
remove: PublicationFileGetByDocumentIdOutPut;
}
@Injectable({
providedIn: 'root'
})
export class PublicationFileGetByDocumentIdService {
constructor(
private local: PublicationFileLocalRepositoryService,
private remote: PublicationFileRemoteRepositoryService
) { }
async execute(input: PublicationFileGetByDocumentIdInput): Promise<Result<IPublicationFilesSyncResult, HttpErrorResponse>> {
var httpResult = await this.remote.FileListByDocumentId(input);
if(httpResult.isOk()) {
var localResult = await this.local.findAll();
if(localResult.isOk()) {
const serverFiles = httpResult.value.data
const added = [];
const updated = [];
const remove = [];
for (const localItem of localResult.value) {
if (localItem.datePublication !== input.datePublication!) {
localItem.datePublication = input.datePublication;
this.local.update(localItem.id, localItem);
}
}
for (const file of serverFiles) {
const findLocally = await this.local.findOne({ name: file.name });
if (findLocally.isOk() && findLocally.value == null) {
added.push({
...file,
documentId: input.documentId!,
datePublication: input.datePublication,
});
const start = performance.now();
this.local.insert({
...file,
documentId: input.documentId!,
datePublication: input.datePublication,
}).then(() => {
const end = performance.now();
console.log(`Insert duration for file "${file.name}": ${(end - start).toFixed(2)} ms`);
});
}
}
for (const localFile of localResult.value) {
const found = httpResult.value.data.filter((e) => e.name === localFile.name);
if (found.length === 0 && localFile.name) {
remove.push(localFile);
this.local.delete(localFile.id);
}
}
return httpResult.map(() =>({
added,
updated,
remove
}))
}
}
return httpResult.map(() =>({
added: [],
updated: [],
remove: []
}));
}
}
@@ -0,0 +1,32 @@
import { Injectable } from '@angular/core';
import { ActionLocalRepositoryService } from 'src/app/module/actions/data/repository/action-local-repository.service';
import { ActionRemoteRepositoryService } from 'src/app/module/actions/data/repository/action-remote-repository.service';
import { z } from 'zod';
const PublicationGetDocumentByProcessIdOutPutSchema = z.object({
file: z.string(),
extension: z.string(),
name: z.string(),
path: z.string(),
documentId: z.number()
}).array();
// Example usage:
export type PublicationGetDocumentByProcessIdOutPut = z.infer<typeof PublicationGetDocumentByProcessIdOutPutSchema>;
@Injectable({
providedIn: 'root'
})
export class PublicationGetDocumentByProcessIdService {
constructor(
private remote: ActionRemoteRepositoryService,
private local: ActionLocalRepositoryService
) {}
execute(processId: string) {
this.remote
}
}
@@ -0,0 +1,134 @@
import { Injectable } from '@angular/core';
import { PublicationLocalRepositoryService } from 'src/app/module/actions/data/repository/publication-local-repository.service';
import { PublicationRemoteRepositoryService } from 'src/app/module/actions/data/repository/publication-remote-repository.service';
import { z } from 'zod';
import { IPublication } from '../entity/publicationEntity';
import { Result } from 'neverthrow';
import { HttpErrorResponse } from '@angular/common/http';
const PublicationListByProcessIdOutPutSchema = z.object({
processId: z.number(),
documentId: z.number(),
applicationId: z.number(),
organicEntityId: z.number(),
securityId: z.number(),
userId: z.number(),
dateIndex: z.string().datetime(),
phase: z.number(),
title: z.string(),
message: z.string(),
datePublication: z.string().datetime(),
isExported: z.boolean(),
sourceLocation: z.number(),
sourceProcessId: z.number(),
sourceDocumentId: z.number(),
}).array();
// Example usage:
export type PublicationListByProcessIdOutPut = z.infer<typeof PublicationListByProcessIdOutPutSchema>;
export interface IPublicationSyncResult {
added: IPublication[];
updated: IPublication[];
remove: IPublication[];
}
@Injectable({
providedIn: 'root'
})
export class PublicationListByProcessIdService {
constructor(
private remote: PublicationRemoteRepositoryService,
private local: PublicationLocalRepositoryService,
) {}
async execute(processId: number): Promise<Result<IPublicationSyncResult, HttpErrorResponse>> {
const result = await this.remote.listByProcessId(processId);
if(result.isOk()) {
const publications = result.value.data.data || [];
var localList = await this.local.findAll();
if(localList.isOk()) {
const localMap = new Map(
localList.value.map(item => [item.documentId.toString(), item])
);
var serverMap = new Map(
publications.map(item => [item.documentId.toString(), item])
);
const added = [];
const updated = [];
const remove = [];
console.log("local::", localList.value.length);
console.log("server::", publications.length);
// detect added & updated
for (const [id, serverItem] of serverMap) {
if (!localMap.has(id)) {
console.log(localList.value.map(item => item.documentId.toString()).join(","), id);
added.push(serverMap.get(id));
} else if (serverItem.datePublication !== localMap.get(id).datePublication) {
updated.push(serverMap.get(id));
console.log('update');
} else {
console.log('else');
console.log(localMap, serverMap);
}
}
// detect removed
for (const [id, localItem] of Object.keys(localMap)) {
if (!serverMap.has(id)) {
remove.push(localMap.get(id));
}
}
console.log("update::", Object.keys(updated).length);
console.log("added::", added.length);
console.log("remove::", remove.length);
// apply updates
if (updated.length > 0) {
await this.local.updateMany(Object.values(updated));
}
// apply removals
for (const deletedItem of remove) {
const findRequest = await this.local.findOne({
documentId: deletedItem.documentId
});
if (findRequest.isOk()) {
await this.local.delete(findRequest.value.documentId!);
}
}
// apply inserts
if (added.length > 0) {
await this.local.insertMany(added);
}
return result.map(()=>({
added,
updated,
remove
}))
}
}
return result.map(()=>({
added: [],
updated: [],
remove: []
}))
}
}