Secure values to prevent unplanned updates

‘price’ (‘prijs’) is data already inserted by a csv file
The user has already many articles inserted

		'Artikel': collection ['post'] @small {
			'losse post': stategroup @default: 'nee' (
				'nee' {
					'soort': text -> ^ ^ ^ ^ .'Componenten'.'Soorten'[]
					'prijs': number 'euro' = >'soort'.'prijs'
				}
				'ja' {
					'soort': text ~> ^ ^ ^ ^ .'Componenten'.'Soorten'[]
					'prijs': number 'euro' //= >'soort'.'prijs'
				}
			)
			'prijs': number 'euro' = switch .'losse post' (
				|'ja' as $'p' => $'p'.'prijs'
				|'nee' as $'p' => $'p'.'prijs'
			)
			'aantal artikelen': number 'aantal'
			'totaal prijs': number 'euro'= from 'euro' product ( .'aantal artikelen' as 'aantal' , .'prijs' )
        	}

‘prijs’ should no be changed when prices are update by csv file.
in case losse post = ‘ja’ this is not an issue, but it is when losse post = ‘nee’.
my solution now is:

			'losse post': stategroup @default: 'nee' (
				'nee' {
					'soort': text -> ^ ^ ^ ^ .'Componenten'.'Soorten'[]
					'Prijs': number 'euro' = >'soort'.'prijs'
					'prijs': number 'euro' @default: 0 // Prijs unknown before save!
					'update prijs': action { 
						'Prijs': number 'euro' @default: .'Prijs' 
					} => update (	
						'prijs' = @ .'Prijs' 
					)
				}

when a new artikel with ‘losse post’ = ‘nee’ is created ‘Prijs’ shows nothing and ‘prijs’ shows 0
and clicking button ‘update prijs’ will show no change.

to secure ‘prijs’ two buttons have to be clicked.
after clicking ‘save’ 'Prijs will show a value, but ‘prijs’ will still be 0
after clicking ‘update prijs’ then prijs will show a value equal to ‘Prijs’.

when later on an artikel is edited then only ‘update prijs’ have to be clicked.
is there a more elegant way to only click ‘update prijs’ without clicking ‘save’ first ?

If ‘prijs’ is not meant to be updated by the user directly (e.g. by csv upload), maybe it should be protected using user rights. When you want to update the price, use a command to set the new value.

Pseudo code (don’t know if this will compile)

'lock': stategroup (
	'locked' { }
	'unlocked' { }
)
'prices': group {
	can-update: ^ . 'lock'?'unlocked'
	'price': number 'amount'
	'update price' {
		'price'
	} => update (
		'price' = @'price'
	)
}

thanks Paul, I’ll need that later on.
in this case however ‘prijs’ is used in a calculation to generate a quotation in excel.
quotation price must always be equal to calculation price, even after a csv upload
in new calculations however the latest updated ‘prijs’ should be used to generate a new quotation.

my question is about the save action that has to be done by new calculations to fill ‘Prijs’ before ‘update prijs’ can be used to fill ‘prijs’. a calculation can give the wrong result if forgotten by a new calculation.

@AntonF I think this is what you are looking for:

'Artikel': collection ['post'] @small {
	'post': text
	'losse post': stategroup @default: 'nee' (
		'nee' {
			'soort': text -> ^ ^ ^ ^ .'Componenten'.'Soorten'[]
		}
		'ja' {
			'soort': text ~> ^ ^ ^ ^ .'Componenten'.'Soorten'[]
		}
	)
	'prijs': number 'euro' @default: switch .'losse post' (
		|'ja' as $'p' => $'p'>'soort'.'prijs'
		|'nee' as $'p' => $'p'>'soort'.'prijs'
	)
	'aantal artikelen': number 'aantal'
	'totaal prijs': number 'euro'= from 'euro' product ( .'aantal artikelen' as 'aantal' , .'prijs' )
}

This way, the price does not change when updating price data for Soorten.

Thanks Gerben,
if I understand correctly, stategroup ‘losse post’ will already prevent ‘prijs’ to be affected when updating data for soorten. if this is true I was not aware of that.
there is therefore no problem in the code of my first question and an action button is not needed?

In your example, the prijs for Artikel was a derived (computed) value. Derived values are always recomputed when values they depend on, change.

Based on the explanation of what you are trying to achieve, a derived value is not what you are looking for. You only want to take the prijs from Soorten once for an Artikel when a user creates it. After that, the prijs should no longer be updated.

To that end, I changed prijs to:

'prijs': number 'euro' @default: switch .'losse post' (
	|'ja' as $'p' => $'p'>'soort'.'prijs'
	|'nee' as $'p' => $'p'>'soort'.'prijs'
)

Notice that I use @default: instead of =. This means that the default (initial) value of prijs will be that from the Soorten, if it is available. For .'losse post'?'nee' it may not be available, as you specified that soort is an optional reference in that case.

Indeed you do not need the action. Furthermore, you do not need 3 different prijs attributes and the additional Prijs.

I’ve overlooked the @default: this is just what I needed, very smart and perfect.