@@ -21,8 +21,7 @@ import {
2121 IReportDayData ,
2222 IReportDayGroupByEmployee ,
2323 IGetEmployeeHourlyRateInput ,
24- IEmployeeHourlyRate ,
25- ICurrencyTotals
24+ IEmployeeHourlyRate
2625} from '@gauzy/contracts' ;
2726import { filter , tap } from 'rxjs/operators' ;
2827import { compareDate , distinctUntilChange , extractNumber , isEmpty , isNotEmpty } from '@gauzy/ui-core/common' ;
@@ -98,13 +97,12 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
9897 disableSaveButton = true ;
9998 organizationId : string ;
10099 discountAfterTax : boolean ;
100+ subtotal = 0 ;
101+ total = 0 ;
101102 currency : string ;
102103 selectedLanguage : string ;
103104 selectedDateRange : IDateRangePicker ;
104- totalsByCurrency : Record < string , ICurrencyTotals > ;
105105 private rate = 0 ;
106- private subtotal : Record < string , number > ;
107- private total = 0 ;
108106
109107 private _isEstimate = false ;
110108 @Input ( ) set isEstimate ( val : boolean ) {
@@ -349,8 +347,8 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
349347 type : 'text' ,
350348 isFilterable : false ,
351349 width : '13%' ,
352- valuePrepareFunction : ( cell , row ) => {
353- return `${ row ?. row ?. data ?. currency ?? '' } ${ cell ?? 0 } ` ;
350+ valuePrepareFunction : ( cell ) => {
351+ return `${ this . currency } ${ cell ?? this . rate } ` ;
354352 }
355353 } ;
356354 quantity = {
@@ -390,8 +388,8 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
390388 type : 'text' ,
391389 isAddable : false ,
392390 isEditable : false ,
393- valuePrepareFunction : ( cell , row : any ) => {
394- return `${ row ?. row ?. data ?. currency ?? '' } ${ parseFloat ( cell ?? '0' ) ?. toFixed ( 2 ) ?? ( 0 ) . toFixed ( 2 ) } ` ;
391+ valuePrepareFunction : ( cell : string ) => {
392+ return `${ this . currency } ${ parseFloat ( cell ?? '0' ) ?. toFixed ( 2 ) ?? ( 0 ) . toFixed ( 2 ) } ` ;
395393 } ,
396394 isFilterable : false ,
397395 width : '13%'
@@ -453,16 +451,11 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
453451 } = this . form . value ;
454452
455453 try {
456- const amounts = Object . entries ( this . totalsByCurrency ) . map ( ( [ currency , values ] : any ) => ( {
457- currency,
458- totalValue : values . total ,
459- organizationId,
460- tenantId
461- } ) ) ;
462454 const createdInvoice = await this . invoicesService . addOwn ( {
463455 invoiceNumber,
464456 invoiceDate : moment ( invoiceDate ) . startOf ( 'day' ) . toDate ( ) ,
465457 dueDate : moment ( dueDate ) . endOf ( 'day' ) . toDate ( ) ,
458+ currency : this . currency ,
466459 discountValue,
467460 discountType,
468461 tax,
@@ -471,7 +464,7 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
471464 tax2Type,
472465 terms : notes ,
473466 paid : false ,
474- amounts ,
467+ totalValue : + this . total . toFixed ( 2 ) ,
475468 fromUserId : this . selectedEmployee ?. id ,
476469 fromOrganizationId : organizationId ,
477470 organizationId,
@@ -746,7 +739,7 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
746739 ) ;
747740 }
748741
749- private loadInvoiceEmployeeRateData ( ) : Observable < IEmployeeHourlyRate [ ] > {
742+ private loadInvoiceEmployeeRateData ( ) : Observable < number > {
750743 const request : IGetEmployeeHourlyRateInput = {
751744 organizationId : this . organization . id ,
752745 startDate : this . selectedDateRange . startDate . toISOString ( ) ,
@@ -755,28 +748,15 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
755748 } ;
756749
757750 return this . employeeRateService . getEmployeeHourlyRate ( request ) . pipe (
758- map ( ( data : IEmployeeHourlyRate [ ] = [ ] ) => {
759- const unique = data . filter (
760- ( item , index , self ) =>
761- index ===
762- self . findIndex (
763- ( t ) =>
764- t . billRateCurrency === item . billRateCurrency && t . billRateValue === item . billRateValue
765- )
766- ) ;
767- // sort by lastUpdate ascending
768- const sorted = unique . sort (
769- ( a , b ) => new Date ( a . lastUpdate ) . getTime ( ) - new Date ( b . lastUpdate ) . getTime ( )
770- ) ;
771-
772- // take the last (most recent) one
773- const last = sorted [ sorted . length - 1 ] ;
774- if ( last ) {
775- this . rate = last . billRateValue ;
776- this . currency = last . billRateCurrency ;
751+ map ( ( data : IEmployeeHourlyRate [ ] ) => {
752+ if ( data && data . length > 0 ) {
753+ const rate = data [ 0 ] ;
754+ this . rate = rate . billRateValue ;
755+ this . currency = rate . billRateCurrency ;
756+ return this . rate ;
757+ } else {
758+ return 0 ;
777759 }
778-
779- return sorted ;
780760 } ) ,
781761 untilDestroyed ( this )
782762 ) ;
@@ -900,16 +880,9 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
900880 switch ( this . selectedInvoiceType ) {
901881 case InvoiceTypeEnum . BY_EMPLOYEE_HOURS :
902882 if ( isNotEmpty ( this . selectedEmployee ) ) {
903- const { time, rates } = await this . getEmployeeData ( ) ;
904- rates . forEach ( ( rate ) => {
905- const data = this . createInvoiceData (
906- this . selectedEmployee ?. name ,
907- rate . billRateValue ,
908- time ,
909- rate . billRateCurrency
910- ) ;
911- invoiceData . push ( data ) ;
912- } ) ;
883+ const { time, rate } = await this . getEmployeeData ( ) ;
884+ const data = this . createInvoiceData ( this . selectedEmployee ?. name , rate , time ) ;
885+ invoiceData . push ( data ) ;
913886 }
914887 break ;
915888 case InvoiceTypeEnum . BY_PROJECT_HOURS :
@@ -960,21 +933,14 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
960933 await generateData ( ) ;
961934
962935 if ( isNotEmpty ( invoiceData ) ) {
963- const subtotal : Record < string , number > = { } ;
936+ let subtotal = 0 ;
964937
965938 invoiceData . forEach ( ( data ) => {
966- const currency = data . currency || this . currency ;
967- const lineTotal = + data . price * + data . quantity ;
968-
969- if ( ! subtotal [ currency ] ) {
970- subtotal [ currency ] = 0 ;
971- }
972-
973- subtotal [ currency ] += lineTotal ;
939+ subtotal += + data . price * + data . quantity ;
974940 } ) ;
975941 this . subtotal = subtotal ;
976942 } else {
977- this . subtotal = { } ;
943+ this . subtotal = 0 ;
978944 }
979945
980946 this . shouldLoadTable = true ;
@@ -984,20 +950,16 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
984950 this . calculateTotal ( ) ;
985951 }
986952
987- getCurrencies ( ) : string [ ] {
988- return this . totalsByCurrency ? Object . keys ( this . totalsByCurrency ) : [ ] ;
989- }
990-
991953 private getEmployeeData ( ) {
992- return new Promise < { time : number ; rates : IEmployeeHourlyRate [ ] } > ( ( resolve , reject ) => {
954+ return new Promise < { time : number ; rate : number } > ( ( resolve , reject ) => {
993955 forkJoin ( {
994956 time : this . loadInvoiceTimeLogsData ( ) ,
995- rates : this . loadInvoiceEmployeeRateData ( )
957+ rate : this . loadInvoiceEmployeeRateData ( )
996958 } )
997959 . pipe ( untilDestroyed ( this ) )
998960 . subscribe ( {
999- next : ( { time, rates } ) => {
1000- resolve ( { time, rates } ) ;
961+ next : ( { time, rate } ) => {
962+ resolve ( { time, rate } ) ;
1001963 } ,
1002964 error : ( err ) => {
1003965 this . toastrService . error ( err ?. message || 'An unknown error occurred' ) ;
@@ -1041,43 +1003,33 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
10411003 this . form . value . discountValue && this . form . value . discountValue > 0 ? this . form . value . discountValue : 0 ;
10421004 const tax = this . form . value . tax && this . form . value . tax > 0 ? this . form . value . tax : 0 ;
10431005 const tax2 = this . form . value . tax2 && this . form . value . tax2 > 0 ? this . form . value . tax2 : 0 ;
1006+ let totalDiscount = 0 ;
1007+ let totalTax = 0 ;
10441008 const tableData = await this . smartTableSource . getAll ( ) ;
1045- const totalsByCurrency : Record < string , ICurrencyTotals > = { } ;
1046-
1047- tableData . forEach ( ( item ) => {
1048- const currency = item . currency || this . currency ;
1049- const lineTotal = + item . price * + item . quantity ;
1050-
1051- if ( ! totalsByCurrency [ currency ] ) {
1052- totalsByCurrency [ currency ] = { subtotal : 0 , totalTax : 0 , totalDiscount : 0 , total : 0 } ;
1053- }
1054-
1055- // --- SUBTOTAL ---
1056- totalsByCurrency [ currency ] . subtotal += lineTotal ;
1057-
1009+ for ( const item of tableData ) {
10581010 // --- TAX ---
10591011 if ( item . applyTax ) {
10601012 switch ( this . form . value . taxType ) {
10611013 case DiscountTaxTypeEnum . PERCENT :
1062- totalsByCurrency [ currency ] . totalTax += lineTotal * ( + tax / 100 ) ;
1014+ totalTax += item . totalValue * ( + tax / 100 ) ;
10631015 break ;
10641016 case DiscountTaxTypeEnum . FLAT_VALUE :
1065- totalsByCurrency [ currency ] . totalTax += + tax ;
1017+ totalTax += + tax ;
10661018 break ;
10671019 default :
1068- totalsByCurrency [ currency ] . totalTax = 0 ;
1020+ totalTax = 0 ;
10691021 break ;
10701022 }
10711023
10721024 switch ( this . form . value . tax2Type ) {
10731025 case DiscountTaxTypeEnum . PERCENT :
1074- totalsByCurrency [ currency ] . totalTax += lineTotal * ( + tax2 / 100 ) ;
1026+ totalTax += item . totalValue * ( + tax2 / 100 ) ;
10751027 break ;
10761028 case DiscountTaxTypeEnum . FLAT_VALUE :
1077- totalsByCurrency [ currency ] . totalTax += + tax2 ;
1029+ totalTax += + tax2 ;
10781030 break ;
10791031 default :
1080- totalsByCurrency [ currency ] . totalTax = 0 ;
1032+ totalTax += + tax2 ;
10811033 break ;
10821034 }
10831035 }
@@ -1087,40 +1039,25 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
10871039 switch ( this . form . value . discountType ) {
10881040 case DiscountTaxTypeEnum . PERCENT :
10891041 if ( ! this . discountAfterTax ) {
1090- totalsByCurrency [ currency ] . totalDiscount += lineTotal * ( + discountValue / 100 ) ;
1042+ totalDiscount += item . totalValue * ( + discountValue / 100 ) ;
10911043 }
10921044 break ;
10931045 case DiscountTaxTypeEnum . FLAT_VALUE :
1094- totalsByCurrency [ currency ] . totalDiscount += + discountValue ;
1046+ totalDiscount += + discountValue ;
10951047 break ;
10961048 default :
1097- totalsByCurrency [ currency ] . totalDiscount = 0 ;
1049+ totalDiscount = 0 ;
10981050 break ;
10991051 }
11001052 }
1101- } ) ;
1102-
1103- // --- DISCOUNT AFTER TAX ---
1104- Object . keys ( totalsByCurrency ) . forEach ( ( currency ) => {
1105- if ( this . discountAfterTax && this . form . value . discountType === DiscountTaxTypeEnum . PERCENT ) {
1106- totalsByCurrency [ currency ] . totalDiscount =
1107- ( totalsByCurrency [ currency ] . subtotal + totalsByCurrency [ currency ] . totalTax ) *
1108- ( + discountValue / 100 ) ;
1109- }
1110-
1111- // --- TOTAL ---
1112- totalsByCurrency [ currency ] . total =
1113- totalsByCurrency [ currency ] . subtotal -
1114- totalsByCurrency [ currency ] . totalDiscount +
1115- totalsByCurrency [ currency ] . totalTax ;
1116-
1117- if ( totalsByCurrency [ currency ] . total < 0 ) totalsByCurrency [ currency ] . total = 0 ;
1118- } ) ;
1119-
1120- this . totalsByCurrency = totalsByCurrency ;
1121-
1122- // Global total across all currencies
1123- this . total = Object . values ( totalsByCurrency ) . reduce ( ( acc , cur ) => acc + cur . total , 0 ) ;
1053+ }
1054+ if ( this . discountAfterTax && this . form . value . discountType === DiscountTaxTypeEnum . PERCENT ) {
1055+ totalDiscount = ( this . subtotal + totalTax ) * ( + discountValue / 100 ) ;
1056+ }
1057+ this . total = this . subtotal - totalDiscount + totalTax ;
1058+ if ( this . total < 0 ) {
1059+ this . total = 0 ;
1060+ }
11241061
11251062 // Update pagination
11261063 this . setPagination ( {
@@ -1170,11 +1107,7 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
11701107 ) {
11711108 newData = { ...newData , price : extractNumber ( newData . price ) } ;
11721109 const itemTotal = + newData . quantity * + extractNumber ( newData . price ) ;
1173- newData . totalValue = itemTotal ;
1174- // Update subtotal for currency
1175- const currency = newData . currency || this . currency ;
1176- this . subtotal [ currency ] += itemTotal ;
1177-
1110+ this . subtotal += itemTotal ;
11781111 await event . confirm . resolve ( newData ) ;
11791112 await this . calculateTotal ( ) ;
11801113 } else {
@@ -1221,11 +1154,10 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
12211154 const newValue = + newData . quantity * + extractNumber ( event . newData . price ) ;
12221155 newData . totalValue = newValue ;
12231156
1224- const currency = newData . currency || this . currency ;
12251157 if ( newValue > oldValue ) {
1226- this . subtotal [ currency ] += newValue - oldValue ;
1158+ this . subtotal += newValue - oldValue ;
12271159 } else if ( oldValue > newValue ) {
1228- this . subtotal [ currency ] -= oldValue - newValue ;
1160+ this . subtotal -= oldValue - newValue ;
12291161 }
12301162 await event . confirm . resolve ( newData ) ;
12311163 await this . calculateTotal ( ) ;
@@ -1239,8 +1171,7 @@ export class InvoiceAddByRoleComponent extends PaginationFilterBaseComponent imp
12391171 }
12401172
12411173 async onDeleteConfirm ( event ) {
1242- const currency = event . data . currency || this . currency ;
1243- this . subtotal [ currency ] -= + event . data . quantity * + event . data . price ;
1174+ this . subtotal -= + event . data . quantity * + event . data . price ;
12441175 await event . confirm . resolve ( event . data ) ;
12451176 await this . calculateTotal ( ) ;
12461177 }
0 commit comments