anchor.diff:  			{grant, Entry, ReserveAmount}
   	end.
   
  --spec reserve_units(SubscriberID, RequestType,
  -		Attributes, UnitType, ReserveAmount, DebitAmount) -> Result
  -	when
  -		SubscriberID :: string() | binary(),
  -		RequestType :: 1..3,
  -		Attributes :: [tuple()],
  -		UnitType :: octets | seconds,
  -		ReserveAmount :: integer(),
  -		DebitAmount :: integer(),
  -		Result :: {ok, GrantedAmount} | {out_of_credit, SessionList} | {error, Reason},
  -		GrantedAmount :: integer(),
  -		SessionList :: [tuple()],
  -		Reason :: term().
  -reserve_units(SubscriberID, RequestType, Attributes,
  -		UnitType, ReserveAmount, DebitAmount) when is_list(SubscriberID) ->
  -	reserve_units(list_to_binary(SubscriberID), RequestType,
  -			Attributes, UnitType, ReserveAmount, DebitAmount);
  -reserve_units(SubscriberID, RequestType, Attributes,
  -		UnitType, ReserveAmount, DebitAmount) ->
  -	F = fun() ->
  -			case mnesia:read(subscriber, SubscriberID, read) of
  -				[#subscriber{buckets = Buckets, product =
  -						#product_instance{product = ProdID, characteristics = Chars},
  -						session_attributes = SessionAttributes} = Subscriber] ->
  -					Product = mnesia:read(product, ProdID),
  -					Validity = proplists:get_value(validity, Chars),
  -					case RequestType of
  -						?initial ->
  -							SA = update_session(Attributes, SessionAttributes),
  -							case reserve_units1(?initial, Product, Subscriber, UnitType,
  -									false, ReserveAmount, DebitAmount, Validity, Buckets) of
  -								out_of_credit ->
  -									mnesia:write(Subscriber#subscriber{session_attributes = []}),
  -									{out_of_credit, SA};
  -								Result ->
  -									mnesia:write(Subscriber#subscriber{session_attributes = SA}),
  -									Result
  -							end;
  -						_ ->
  -							case reserve_units1(RequestType, Product, Subscriber,
  -									UnitType, true, ReserveAmount, DebitAmount, Validity, Buckets) of
  -								out_of_credit ->
  -									mnesia:write(Subscriber#subscriber{session_attributes = []}),
  -									{out_of_credit, SessionAttributes};
  -								Result ->
  -									Result
  -							end
  -					end;
  -				[] ->
  -					throw(subscriber_not_found)
  -			end
  -	end,
  -	case mnesia:transaction(F) of
  -		{atomic, {out_of_credit, SessionList}} ->
  -			{out_of_credit, SessionList};
  -		{atomic, {grant, GrantAmount}} ->
  -			{ok, GrantAmount};
  -		{aborted, {throw, Reason}} ->
  -			{error, Reason};
  -		{aborted, Reason} ->
  -			{error, Reason}
  -	end.
  -%% @hidden
  -reserve_units1(?initial, Product, Subscriber, UnitType, Flag, ReserveAmount, _DebitAmount, Validity, Buckets) ->
  -	case debit_units(Subscriber, Product, UnitType, Flag, ReserveAmount, Validity, Buckets) of
  -		{Charged, _NewBuckets} when Charged =< 0 ->
  -			out_of_credit;
  -		{_Chraged, _NewBuckets} ->
  -			{grant, ReserveAmount}
  -	end;
  -reserve_units1(_, Product, Subscriber, UnitType, Flag, ReserveAmount, DebitAmount, Validity, Buckets) ->
  -	case debit_units(Subscriber, Product, UnitType, Flag, DebitAmount, Validity, Buckets) of
  -		{Charged, NewBuckets} when Charged =< 0 andalso DebitAmount =/= 0 ->
  -			out_of_credit;
  -		{_Charged, NewBuckets} ->	
  -			case debit_units(Subscriber, Product, UnitType, Flag, ReserveAmount, Validity, Buckets) of
  -				{Ch1, _NB1} when Ch1 =< 0 andalso ReserveAmount =/=0  ->
  -					out_of_credit;
  -				_ ->
  -					{grant, ReserveAmount}
  -			end
  -	end.
  -%% @hidden
  -debit_units(Subscriber, [#product{price = Prices}], Type, Flag, DebitAmount, Validity, Buckets) ->
  -	case charge(Type, DebitAmount, Flag, Buckets) of
  -		{Charged, NewBuckets} when Charged < DebitAmount ->
  -			mnesia:write(Subscriber#subscriber{buckets = NewBuckets}),
  -			case lists:keyfind(usage, #price.type, Prices) of
  -				#price{units = Type, size = Size, amount = Price} ->
  -					purchase(Type, Price, Size, DebitAmount - Charged, Validity, false, NewBuckets);
  -				false ->
  -					throw(price_not_found)
  -			end;
  -		{Charged, NewBuckets} ->
  -			mnesia:write(Subscriber#subscriber{buckets = NewBuckets}),
  -			{Charged, NewBuckets}
  -	end.
  -
  -
  -
  --spec rating(SubscriberID, Final, UsageSecs, UsageOctets, Attributes) -> Return
  -	when
  -		SubscriberID :: string() | binary(),
  -		Final :: boolean(),
  -		UsageSecs :: integer(),
  -		UsageOctets :: integer(),
  -		Attributes :: [[tuple()]],
  -		Return :: {ok, #subscriber{}} | {out_of_credit, SessionAttributes} | {error, Reason},
  -		SessionAttributes :: [tuple()],
  -		Reason :: term().
  -rating(SubscriberID, Final, UsageSecs, UsageOctets, Attributes) when is_list(SubscriberID) ->
  -	rating(list_to_binary(SubscriberID), Final, UsageSecs, UsageOctets, Attributes);
  -rating(SubscriberID, Final, UsageSecs, UsageOctets, Attributes) when is_binary(SubscriberID) ->
  -	F = fun() ->
  -			case mnesia:read(subscriber, SubscriberID, write) of
  -				[#subscriber{buckets = Buckets,
  -						session_attributes = SessionList,
  -						product = #product_instance{product = ProdID,
  -						characteristics = Chars}} = Subscriber] ->
  -					Validity = proplists:get_value(validity, Chars),
  -					case mnesia:read(product, ProdID, read) of
  -						[#product{price = Prices}] ->
  -							case lists:keyfind(usage, #price.type, Prices) of
  -								#price{} = Price ->
  -									case rating2(Price,
  -												Validity, UsageSecs, UsageOctets, Final, Buckets) of
  -										{Charged, NewBuckets} when Charged =< 0 ->
  -											Entry = Subscriber#subscriber{buckets = NewBuckets,
  -													session_attributes = []},
  -											mnesia:write(Entry),
  -											{out_of_credit, SessionList};
  -										{_, NewBuckets} ->
  -											NewSessionList = case Final of
  -												true ->
  -													remove_session(SessionList, Attributes);
  -												false ->
  -													SessionList
  -											end,
  -											Entry = Subscriber#subscriber{buckets = NewBuckets,
  -													session_attributes = NewSessionList},
  -											mnesia:write(Entry),
  -											Entry
  -									end;
  -								false ->
  -									throw(price_not_found)
  -							end;
  -						[] ->
  -							throw(product_not_found)
  -					end;
  -				[] ->
  -					throw(subscriber_not_found)
  -			end
  -	end,
  -	case mnesia:transaction(F) of
  -		{atomic, #subscriber{} = Sub} ->
  -			{ok, Sub};
  -		{atomic, {out_of_credit, SL}} ->
  -			{out_of_credit, SL};
  -		{aborted, {throw, Reason}} ->
  -			{error, Reason};
  -		{aborted, Reason} ->
  -			{error, Reason}
  -	end.
  -%% @hidden
  -rating2(#price{type = usage, size = Size, units = octets,
  -		amount = Amount}, Validity, _UsageSecs, UsageOctets, Final, Buckets) ->
  -	rating3(Amount, Size, octets, Validity, UsageOctets, Final, Buckets);
  -rating2(#price{type = usage, size = Size, units = seconds,
  -		amount = Amount}, Validity, UsageSecs, _UsageOctets, Final, Buckets) ->
  -	rating3(Amount, Size, seconds, Validity, UsageSecs, Final, Buckets).
  -%% @hidden
  -rating3(Price, Size, Type, Validity, Used, Final, Buckets) ->
  -	case charge(Type, Used, Final, Buckets) of
  -		{Charged, NewBuckets} when Charged < Used ->
  -			purchase(Type, Price, Size, Used - Charged, Validity, Final, NewBuckets);
  -		{Charged, NewBuckets} ->
  -			{Charged, NewBuckets}
  -	end.
  -
   %%----------------------------------------------------------------------
   %%  internal functions
   %%----------------------------------------------------------------------
  
positive.code: -module(ocs_rating).
  -copyright('Copyright (c) 2016 - 2017 SigScale Global Inc.').
  
  -export([rating/5]).
  -export([remove_session/2]).
  -export([reserve_units/6]).
  
  -export([rate/4, rate/5]).
  -export([charge/4]).
  
  
negative.code: %% support deprecated_time_unit()
  -define(MILLISECOND, milli_seconds).
  %-define(MILLISECOND, millisecond).
  
  -spec rate(SubscriberID, Flag, DebitAmount, ReserveAmount) -> Result
  	when
  