Commit 059369e5 authored by hasan khaddour's avatar hasan khaddour

fix attachment and spends

parent 21546edb
......@@ -14,7 +14,7 @@
<div class="row align-items-center justify-content-between">
<div class="col text-center">
<small>
<button class="btn btn-primary">تنزيل </button>
<button (click)="download()" class="btn btn-primary">تنزيل </button>
</small>
</div>
......
//#region Imports
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Attachment } from '../../models/responses/attachment';
import { ConfigurationService } from '../../../core/services/configuration/configuration.service';
import { ProjectService } from '../../services/project.service';
import { last } from 'rxjs';
//#endregion Imports
@Component({
selector: 'attahment-item',
......@@ -8,21 +13,67 @@ import { ConfigurationService } from '../../../core/services/configuration/confi
styleUrl: './attahment-item.component.css'
})
export class AttahmentItemComponent {
//#region Dependencies
@Input() attachment : Attachment
@Output() selected = new EventEmitter<Attachment>()
@Output() detled = new EventEmitter<Attachment>()
//#endregion Dependencies
//#region Constructor
constructor(
private projectService :ProjectService,
public config :ConfigurationService
){}
//#endregion Constructor
//#region Selction
onSelected() {
this.selected.emit(this.attachment)
}
//#endregion Selction
//#region Download
onDelete() {
this.detled.emit(this.attachment);
}
download() {
this
.projectService
.getAttacmenfFile(this.attachment.id,this.attachment.attachmentUrl)
.subscribe({
next: (response) => {
const fileName =this.attachment.attachmentName+"."+this.attachment.attachmentUrl.split('.').reverse()[0];
// Create a new Blob object using the response data
const blob = new Blob([response], { type: response.type });
// Create a URL for the Blob object
const url = window.URL.createObjectURL(blob);
// Create a link element
const a = document.createElement('a');
a.href = url;
a.download = fileName; // Set the file name for download
document.body.appendChild(a); // Append the link to the body
a.click(); // Simulate a click on the link to start download
document.body.removeChild(a); // Remove the link from the body
window.URL.revokeObjectURL(url); // Clean up the URL object
}
,
error:(error) => {
console.error('Error downloading file', error);
}
});
}
//#endregion Download
}
......@@ -26,8 +26,8 @@ export class AddAttachmentModalComponent {
ngOnInit(): void {
this.item ={
attachmentName:'اسم المرفق',
attachmentDescription:'وصف المرفق',
attachmentName:'',
attachmentDescription:'',
file:null,
projectId:this.projectId
}
......@@ -45,8 +45,7 @@ export class AddAttachmentModalComponent {
next: (data)=>{
this.itemAdded.emit();
this.activeModal.close(data); // Close modal and pass data
this.activeModal.close(true); // Close modal and pass data
},
error: (err )=> this.toastr.error("لقد حدث خطاء ما")
......
......@@ -23,9 +23,9 @@
</div>
<div class="row">
<div class="mb-3 col-8 offset-1" >
<div class="mb-3 col-9 offset-1" >
<label for="decription" class="form-label">البيان</label>
<textarea col="3" name="worker" id="decription" class="form-control" [(ngModel)]="request.description" required>
<textarea col="4" name="worker" id="decription" class="form-control" [(ngModel)]="request.description" minlength="15" required>
</textarea>
</div>
</div>
......
......@@ -33,8 +33,8 @@ export class AddFinancialSpendModalComponent {
};
}
onSubmit(): void {
// Emit the project data or handle it as needed
console.log('Project data submitted:', this.request);
this.financialService.addSpendItem(this.request).subscribe({
next: (data)=>{
......
......@@ -28,6 +28,7 @@ export class RemoveAttachmentModalComponent {
.subscribe({
next : ()=>{
this.attachmentRemoved.emit();
this.activeModal.close(true)
},
error:(err)=>{
......
......@@ -41,6 +41,7 @@
</div>
<!-- .card -->
</div>
<!-- .col -->
<div
class="col-md-6 col-lg-4"
......@@ -77,4 +78,21 @@
</div> <!-- .card-body -->
</div> <!-- .card -->
</div>
\ No newline at end of file
<div class="col-md-6 col-lg-4" [routerLink]="['/reports/spends/',project.id]">
<div class="card shadow mb-4">
<div class="card-body file-list">
<div class="d-flex align-items-center">
<div class="text-center">
<div class="circle circle-md bg-secondary">
<span class="fe fe-users fe-16 text-white"></span>
</div>
</div>
<div class="flex-fill ml-4 fname">
<strong>خطة الإنفاق السنوية</strong><br />
</div>
</div>
</div>
<!-- .card-body -->
</div>
<!-- .card -->
</div>
......@@ -18,7 +18,7 @@
</div> <!-- .card-body -->
</div> <!-- .card -->
</div>
<div class="col-md-6 col-lg-4" *ngIf="project.currentState.toLowerCase()=='inplan'" (click)="onComplete()" >
<div class="col-md-6 col-lg-4" *ngIf="project.currentState.toLowerCase()=='inprogress'" (click)="onComplete()" >
<div class="card shadow mb-4">
<div class="card-body file-list">
<div class="d-flex align-items-center">
......
......@@ -5,3 +5,8 @@ export interface Attachment {
attachmentName :string
attachmentDescription :string
}
export interface AttachmentFile {
file : File
attachmentName :string
attachmentDescription :string
}
......@@ -8,4 +8,38 @@ export class FinancialSpending {
ammount: number;
currency: string;
};
static aggregateSpendingByYearAndCurrency(spendings: FinancialSpending[]): FinancialSpending[] {
const aggregationMap: Record<string, FinancialSpending> = {};
spendings.forEach(spending => {
const year = new Date(spending.expectedSpendingDate).getFullYear();
const currency = spending.externalPurchase.currency;
// Create a unique key for each year-currency combination
const key = `${year}-${currency}`;
if (!aggregationMap[key]) {
// Initialize an aggregated entry for this year-currency combination
aggregationMap[key] = {
id: 0, // Aggregated entries do not have an ID
expectedSpendingDate: new Date(`${year}-01-01`), // Use the first day of the year for aggregation
costType: 'Aggregated', // Set as 'Aggregated'
description: `Aggregated spending for ${currency} in ${year}`,
localPurchase: 0,
externalPurchase: {
ammount: 0,
currency: currency
}
};
}
// Aggregate values
aggregationMap[key].localPurchase += spending.localPurchase;
aggregationMap[key].externalPurchase.ammount += spending.externalPurchase.ammount;
});
// Convert the aggregation map back to a list
return Object.values(aggregationMap);
}
}
......@@ -56,6 +56,7 @@ export class FinancialSpendingComponent {
pageNumber: null ,
pageSize: null
}
this.financialService.getSpendByProject(request).subscribe({
next: (data)=> {
this.spends= data
......@@ -139,10 +140,7 @@ export class FinancialSpendingComponent {
}
closeModal(): void {
const modalElement = document.getElementById('projectModal');
if (modalElement) {
new Modal(modalElement).hide(); // Close the modal
}
this.modalService.dismissAll();
}
......@@ -152,9 +150,8 @@ export class FinancialSpendingComponent {
modalRef.result.then((result) => {
if (result) {
// Add the new project to the list
this.spends.push(result);
console.log('Project added:', result);
}
}, (reason) => {
// Handle modal dismiss
......
......@@ -47,7 +47,7 @@ export class ProjectAttachmentsComponent implements OnInit{
this.toastr.success('تم تحميل المرفقات بنجاح')
}
this.attachments=data
this.attachments=[...data]
}
,
error:(err)=>{
......@@ -69,8 +69,7 @@ export class ProjectAttachmentsComponent implements OnInit{
modalRef.result.then((result) => {
if (result) {
// Add the new project to the list
this.loadAttachment();
this.attachments=this.attachments.filter(e => e.id!= attachment.id)
}
}, (reason) => {
......@@ -84,16 +83,8 @@ export class ProjectAttachmentsComponent implements OnInit{
const modalRef = this.modalService.open(AddAttachmentModalComponent);
modalRef.componentInstance.projectId = this.projectId;
modalRef.componentInstance.itemAdded.subscribe(
{
next : ()=>{
this.loadAttachment()
}
}
);
modalRef.result.then((result) => {
debugger
if (result) {
// Add the new project to the list
this.loadAttachment();
......
//#region Imports
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { ConfigurationService } from '../../core/services/configuration/configuration.service';
......@@ -15,13 +16,13 @@ import { CancelProjectRequest } from '../models/requests/project-requests/Cancel
import { RePlanProjectRequest } from '../models/requests/project-requests/RePlanProjectRequest';
import { CreateProjectRequest } from '../models/requests/project-requests/createProjectRequest';
import { AddAttachmentRequest } from '../models/requests/project-requests/AddAttachmentRequest';
import { Attachment } from '../models/responses/attachment';
import { Attachment, AttachmentFile } from '../models/responses/attachment';
import { CompleteProjectRequest } from '../models/requests/project-requests/completeProjectRequest';
import { ChangeEmployeeParticipationRequest } from '../models/requests/project-requests/ChangeEmployeeParticipationRequest';
import { ParticipationChange } from '../models/responses/participationChange';
import { ProjectCompletion } from '../models/responses/ProjectCompletion';
import { EmployeeContribution } from '../models/responses/employeeContribution';
//#endregion Imports
@Injectable({
providedIn: 'root'
})
......@@ -223,6 +224,17 @@ export class ProjectService {
}
return this.http.post<number>(this.config.getServerUrl()+ "/Projects/AddAttachment",formData);
}
public getAttacmenfFile(attachmentId :number,url :string ):Observable<File>{
return this.http.get<File>(`${this.config.getServerUrl()}/Projects/Attachment/`, {
params: { attachmentId: attachmentId.toString(), fileUrl: url },
responseType: 'blob' as 'json' // Specify responseType as 'blob'
});
}
//tihs method responsible for getting the attachments of a project
//
......
<div class="container-fluid" *ngIf="project">
<div class="row justify-content-center">
<div class="col-12">
<div class="row align-items-center mb-4">
<div class="col">
<h2 class="h5 page-title">
<small class="text-muted text-uppercase">بطاقة معلومات مشروع</small>
</h2>
</div>
<div class="col-auto">
<button
type="button"
(click)="downloadAsPdf()"
class="btn mr-1 btn-secondary m-1"
>
طباعة
</button>
<button *ngIf="project.currentState.toLocaleLowerCase()=='completed'" [routerLink]="['/reports/completion',project.id]" type="button" class="btn mr-1 btn-secondary m-1">
تقرير انجاز </button>
<button
type="button"
[routerLink]="['/reports/timeline/', project.id]"
class="btn mr-1 btn-secondary m-1"
>
تقرير خطة زمنية
</button>
</div>
</div>
<div class="card shadow" id="pdfContent">
<div class="card-body p-5">
<project-header [projectInfo]="project.projectInfo"></project-header>
<project-subjective [project]="project"> </project-subjective>
<hr />
<p><strong>خطة الإنفاق السنوية</strong></p>
<table class="table table-borderless table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col" clsss="text-center">العام</th>
<th scope="col" class="text-center">الشراء المحلي </th>
<th scope="col" class="text-center">الشراء الخارجي</th>
<th scope="col" class="text-center">نوع القطع</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let spend of this.spend ;index as i " >
<th scope="row">{{i +1 }}</th>
<td class="text-center"> {{spend.expectedSpendingDate | date }}
</td>
<td class="text-center">{{spend.localPurchase}}</td>
<td class="text-center">{{spend.externalPurchase.ammount}}</td>
<td class="text-center">{{spend.externalPurchase.currency}}</td>
</tr>
<tr *ngIf="spend.length==0" >
<th scope="row"></th>
<td class="text-center"> </td>
<td class="text-center"></td>
<td class="text-center"></td>
<td class="text-center"></td>
</tr>
</tbody>
</table>
<project-footer
[proposer]="project.proposer"
[executer]="project.executer"
[projectManager]="project.projectManager"
[teamLeader]="project.teamLeader"
>
</project-footer>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
<!-- /.col-12 -->
</div>
</div>
\ No newline at end of file
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { PdfDownloaderService } from '../../../core/services/pdfDownloader/pdf-downloader.service';
import { Project } from '../../../projects/models/responses/project';
import { ReportsService } from '../../services/reports.service';
import { FinancialSpending } from '../../../projects/models/responses/financialSpending';
@Component({
selector: 'annual-spend-report',
templateUrl: './annual-spend-report.component.html',
styleUrl: './annual-spend-report.component.css'
})
export class AnnualSpendReportComponent {
project : Project
spend :FinancialSpending[]
constructor(
private reportsService : ReportsService,
private route :ActivatedRoute,
private pdfDownloader : PdfDownloaderService
){}
ngOnInit(): void {
const id = Number(this.route.snapshot.paramMap.get('id'));
this
.reportsService
.getProjectById(id)
.subscribe({
next :(data) => {
debugger
this.project = data;
this.spend=FinancialSpending.aggregateSpendingByYearAndCurrency(data.financialSpending)
},
error : (err)=>{ console.log(err)}
});
}
public downloadAsPdf(): void {
this.pdfDownloader.downloadAsPdf('pdfContent');
}
}
......@@ -23,6 +23,7 @@ import { TrackRowItemComponent } from './componenets/tracks-components/track-row
import { EmployeeWorkTrackComponent } from './pages/employee-work-track/employee-work-track.component';
import { ProjectSubjectivUnformalComponent } from './componenets/project-report-layout/project-subjectiv-unformal/project-subjectiv-unformal.component';
import { StepTrackReportComponent } from './pages/step-track-report/step-track-report.component';
import { AnnualSpendReportComponent } from './pages/annual-spend-report/annual-spend-report.component';
@NgModule({
......@@ -46,7 +47,8 @@ import { StepTrackReportComponent } from './pages/step-track-report/step-track-r
TrackRowItemComponent,
EmployeeWorkTrackComponent,
ProjectSubjectivUnformalComponent,
StepTrackReportComponent
StepTrackReportComponent,
AnnualSpendReportComponent
],
imports: [
CommonModule,
......
......@@ -9,6 +9,7 @@ import { ProjectTrackHistoryComponent } from '../pages/project-track-history/pro
import { StepsTrackReportComponent } from '../pages/steps-track-report/steps-track-report.component';
import { EmployeeWorkTrackComponent } from '../pages/employee-work-track/employee-work-track.component';
import { StepTrackReportComponent } from '../pages/step-track-report/step-track-report.component';
import { AnnualSpendReportComponent } from '../pages/annual-spend-report/annual-spend-report.component';
const routes: Routes = [
{path: 'definition/:id',component:ProjectDefinitionComponent},
......@@ -18,7 +19,8 @@ const routes: Routes = [
{path: 'steps-tracks/:projectId/track/:id',component:StepsTrackReportComponent},
{path: 'history/:projectId',component:ProjectTrackHistoryComponent} ,
{path: 'contributions/:projectId/employee/:employeeId',component:EmployeeWorkTrackComponent} ,
{path: 'history/:projectId/step/:stepId',component:StepTrackReportComponent}
{path: 'history/:projectId/step/:stepId',component:StepTrackReportComponent} ,
{path: 'spends/:id',component:AnnualSpendReportComponent}
......
......@@ -31,16 +31,16 @@ export class AddStepTrackModalComponent {
constructor(private fb: FormBuilder,
private stepService : StepService ,
private toastr :ToastrService
) {
) {}
ngOnInit(): void {
this.stepTrackForm = this.fb.group({
id: [],
stepName: ['', Validators.required],
executionState: ['', Validators.required],
trackExecutionRatio: [0, [Validators.required, Validators.min(0), Validators.max(100)]],
});
}
ngOnInit(): void {
this.stepService.getStepsByProject(this.projectId)
.subscribe({
next: (data)=> {
......
......@@ -25,32 +25,32 @@
<div class="mb-3 col-4">
<label for="performedWork" class="form-label">العمل المنجز</label>
<input id="performedWork" formControlName="performedWork" [(ngModel)]="request.employeeWorkInfo.performedWork" class="form-control" >
<input id="performedWork" name="performedWork" [(ngModel)]="request.employeeWorkInfo.performedWork" class="form-control" >
</div>
<div class="mb-3 col-4">
<label for="assignedWorkEnd" class="form-label">تاريخ تنفيذ العمل المسند</label>
<input type="date" id="assignedWorkEnd" formControlName="assignedWorkEnd" [(ngModel)]="request.employeeWorkInfo.assignedWorkEnd" class="form-control" >
<input type="date" id="assignedWorkEnd" name="assignedWorkEnd" [(ngModel)]="request.employeeWorkInfo.assignedWorkEnd" class="form-control" >
</div>
</div>
<div class="row">
<div class="mb-3 col-4">
<label for="assignedWorkingHours" class="form-label">ساعات العمل المسندة </label>
<input type="number" id="assignedWorkingHours" formControlName="contributingR" [(ngModel)]="request.employeeWork.assignedWorkingHours" class="form-control" >
<input type="number" id="assignedWorkingHours" name="contributingR" [(ngModel)]="request.employeeWork.assignedWorkingHours" class="form-control" >
</div>
<div class="mb-3 col-4">
<label for="workedHours" class="form-label">ساعات العمل الفعلية</label>
<input type="number" id="workedHours" [(ngModel)]="request.employeeWork.workedHours" formControlName="workedHours" class="form-control" >
<input type="number" id="workedHours" [(ngModel)]="request.employeeWork.workedHours" name="workedHours" class="form-control" >
</div>
<div class="mb-3 col-4">
<label for="contributingRatio" class="form-label">نسبة المساهمة في العمل</label>
<input type="number" id="contributingRatio" [(ngModel)]="request.employeeWork.contributingRatio" formControlName="contributingRatio" class="form-control" >
<input type="number" id="contributingRatio" [(ngModel)]="request.employeeWork.contributingRatio" name="contributingRatio" class="form-control" >
</div>
</div>
<button type="submit" class="btn mr-4 ml-4 btn-primary"[disabled]="projectForm.invalid" >إضافة</button>
<button type="submit" class="btn mr-4 ml-4 btn-primary"[disabled]="projectForm.invalid" >تعديل</button>
<div (click)="onClose()" class=" mr-4 ml-4 btn btn-primary" >إلغاء</div>
</form>
......
......@@ -43,6 +43,7 @@ export class UpdateWorkModalComponent implements OnInit {
onSubmit(){
debugger;
this
.trackService
.updateEmployeeWorkTrack(this.request)
......
......@@ -54,7 +54,7 @@ export class ProjectTrackHistoryComponent {
next : (data)=>{
this.toastr.success("تم تحميل عمليات المتابعة بنجاح");
this.tracks= data;
this.tracks= data.sort((e1,e2)=> Number(e1.trackInfo.trackDate > e2.trackInfo.trackDate));
}
,
......@@ -102,7 +102,7 @@ export class ProjectTrackHistoryComponent {
deleteTrack(): void {
let request : RemoveTrackRequest= {
trackId: this.projectId ,
trackId: this.selectedItem.id ,
}
this.trackService.removeTrack(request).subscribe({
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment