mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	Enhancement: allow specifying default currency for Monetary custom field (#7381)
This commit is contained in:
		| @@ -20,6 +20,12 @@ const customFields: CustomField[] = [ | ||||
|       select_options: ['Option 1', 'Option 2', 'Option 3'], | ||||
|     }, | ||||
|   }, | ||||
|   { | ||||
|     id: 5, | ||||
|     name: 'Field 5', | ||||
|     data_type: CustomFieldDataType.Monetary, | ||||
|     extra_data: { default_currency: 'JPY' }, | ||||
|   }, | ||||
| ] | ||||
| const document: Document = { | ||||
|   id: 1, | ||||
| @@ -112,6 +118,18 @@ describe('CustomFieldDisplayComponent', () => { | ||||
|     expect(component.value).toEqual(100) | ||||
|   }) | ||||
|  | ||||
|   it('should respect explicit default currency', () => { | ||||
|     component['defaultCurrencyCode'] = 'EUR' // mock default locale injection | ||||
|     component.fieldId = 5 | ||||
|     component.document = { | ||||
|       id: 1, | ||||
|       title: 'Doc 1', | ||||
|       custom_fields: [{ field: 5, document: 1, created: null, value: '100' }], | ||||
|     } | ||||
|     expect(component.currency).toEqual('JPY') | ||||
|     expect(component.value).toEqual(100) | ||||
|   }) | ||||
|  | ||||
|   it('should show select value', () => { | ||||
|     expect(component.getSelectValue(customFields[3], 2)).toEqual('Option 3') | ||||
|   }) | ||||
|   | ||||
| @@ -90,7 +90,9 @@ export class CustomFieldDisplayComponent implements OnInit, OnDestroy { | ||||
|     )?.value | ||||
|     if (this.value && this.field.data_type === CustomFieldDataType.Monetary) { | ||||
|       this.currency = | ||||
|         this.value.match(/([A-Z]{3})/)?.[0] ?? this.defaultCurrencyCode | ||||
|         this.value.match(/([A-Z]{3})/)?.[0] ?? | ||||
|         this.field.extra_data?.default_currency ?? | ||||
|         this.defaultCurrencyCode | ||||
|       this.value = parseFloat(this.value.replace(this.currency, '')) | ||||
|     } else if ( | ||||
|       this.value?.length && | ||||
|   | ||||
| @@ -28,6 +28,11 @@ | ||||
|             } | ||||
|           </div> | ||||
|         } | ||||
|         @case (CustomFieldDataType.Monetary) { | ||||
|           <div class="my-3"> | ||||
|             <pngx-input-text i18n-title title="Default Currency" hint="3-character currency code" i18n-hint formControlName="default_currency" placeholder="Use locale" i18n-placeholder autocomplete="off"></pngx-input-text> | ||||
|           </div> | ||||
|         } | ||||
|       } | ||||
|     </div> | ||||
|   </div> | ||||
|   | ||||
| @@ -90,6 +90,7 @@ export class CustomFieldEditDialogComponent | ||||
|       data_type: new FormControl(null), | ||||
|       extra_data: new FormGroup({ | ||||
|         select_options: new FormArray([new FormControl(null)]), | ||||
|         default_currency: new FormControl(null), | ||||
|       }), | ||||
|     }) | ||||
|   } | ||||
|   | ||||
| @@ -52,6 +52,11 @@ describe('MonetaryComponent', () => { | ||||
|     expect(component.defaultCurrencyCode).toEqual('BRL') | ||||
|   }) | ||||
|  | ||||
|   it('should support setting a default currency code', () => { | ||||
|     component.defaultCurrency = 'EUR' | ||||
|     expect(component.defaultCurrencyCode).toEqual('EUR') | ||||
|   }) | ||||
|  | ||||
|   it('should parse monetary value correctly', () => { | ||||
|     expect(component['parseMonetaryValue']('123.4')).toEqual('123.4') | ||||
|     expect(component['parseMonetaryValue']('123.4', true)).toEqual('123.40') | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { Component, forwardRef, Inject, LOCALE_ID } from '@angular/core' | ||||
| import { Component, forwardRef, Inject, Input, LOCALE_ID } from '@angular/core' | ||||
| import { NG_VALUE_ACCESSOR } from '@angular/forms' | ||||
| import { AbstractInputComponent } from '../abstract-input' | ||||
| import { getLocaleCurrencyCode } from '@angular/common' | ||||
| @@ -29,11 +29,16 @@ export class MonetaryComponent extends AbstractInputComponent<string> { | ||||
|  | ||||
|   defaultCurrencyCode: string | ||||
|  | ||||
|   @Input() | ||||
|   set defaultCurrency(currency: string) { | ||||
|     if (currency) this.defaultCurrencyCode = currency | ||||
|   } | ||||
|  | ||||
|   constructor(@Inject(LOCALE_ID) currentLocale: string) { | ||||
|     super() | ||||
|  | ||||
|     this.currency = this.defaultCurrencyCode = | ||||
|       getLocaleCurrencyCode(currentLocale) | ||||
|       this.defaultCurrency ?? getLocaleCurrencyCode(currentLocale) | ||||
|   } | ||||
|  | ||||
|   writeValue(newValue: any): void { | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
|         } | ||||
|       </div> | ||||
|       <div class="position-relative" [class.col-md-9]="horizontal"> | ||||
|         <input #inputField type="text" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete"> | ||||
|         <input #inputField type="text" class="form-control" [class.is-invalid]="error" [id]="inputId" [(ngModel)]="value" (change)="onChange(value)" [disabled]="disabled" [autocomplete]="autocomplete" [placeholder]="placeholder"> | ||||
|         @if (hint) { | ||||
|           <small class="form-text text-muted" [innerHTML]="hint | safeHtml"></small> | ||||
|         } | ||||
|   | ||||
| @@ -18,6 +18,9 @@ export class TextComponent extends AbstractInputComponent<string> { | ||||
|   @Input() | ||||
|   autocomplete: string | ||||
|  | ||||
|   @Input() | ||||
|   placeholder: string = '' | ||||
|  | ||||
|   constructor() { | ||||
|     super() | ||||
|   } | ||||
|   | ||||
| @@ -157,6 +157,7 @@ | ||||
|                     @case (CustomFieldDataType.Monetary) { | ||||
|                       <pngx-input-monetary formControlName="value" | ||||
|                       [title]="getCustomFieldFromInstance(fieldInstance)?.name" | ||||
|                       [defaultCurrency]="getCustomFieldFromInstance(fieldInstance)?.extra_data?.default_currency" | ||||
|                       [removable]="userIsOwner" | ||||
|                       (removed)="removeField(fieldInstance)" | ||||
|                       [horizontal]="true" | ||||
|   | ||||
| @@ -57,5 +57,6 @@ export interface CustomField extends ObjectWithId { | ||||
|   created?: Date | ||||
|   extra_data?: { | ||||
|     select_options?: string[] | ||||
|     default_currency?: string | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 shamoon
					shamoon