[m-rev.] diff: ensure that enough attributes are available to tariff risk

Peter Ross pro at missioncriticalit.com
Sat Jan 8 03:00:12 AEDT 2005


Hi,


===================================================================


Check that the questions sufficent for a risk to be tariffed
have been answered before tariffing a risk.  Display information
message if not enough questions have been answered.

If a coverage has been permanently disabled show an error with
a rudimentary tooltip which explains why.

XUL/MAS.xbl:
XUL/skin/MAS.css:
	Fix a bug where variantboolean couldn't contain an error.

mas/mas.m:
	Add a new type available, which allows one to report a
	multi-lingual error message.
	In tariff_risk make sure that all the mandatory attributes
	have values.
	Display the reason why a coverage is not available.
	Add a default value of VERDEFF to the risk, as we have no
	other way of setting this value.

mas/mas.screen.m:
mas/mas.xbl.m:
	Record the status of whether or not a variant_choice has
	been disabled or not.  This attribute is currenlty unused.


Index: XUL/MAS.xbl
===================================================================
RCS file: /var/cvs/map/mas/XUL/MAS.xbl,v
retrieving revision 1.9
diff -u -r1.9 MAS.xbl
--- XUL/MAS.xbl	2005/01/06 13:23:44	1.9
+++ XUL/MAS.xbl	2005/01/07 15:51:40
@@ -205,9 +205,12 @@
 <!--*********************************************************************-->
     <binding id="variantboolean" extends="element.xbl#boolean">
         <content>
+	  <xul:hbox>
             <xul:checkbox xbl:inherits="cssid=id,label,french,dutch,english,german" oncommand="document.getBindingParent(this).action();"/>
             <xul:description xbl:inherits="cssid=id,value=price"/>
             <xul:description xbl:inherits="cssid=id" value="EUR"/>
+	  </xul:hbox>
+	  <children/>
         </content>
         <implementation>
             <method name="getNumericalValue">
Index: XUL/skin/MAS.css
===================================================================
RCS file: /var/cvs/map/mas/XUL/skin/MAS.css,v
retrieving revision 1.5
diff -u -r1.5 MAS.css
--- XUL/skin/MAS.css	2005/01/04 11:48:04	1.5
+++ XUL/skin/MAS.css	2005/01/07 15:51:40
@@ -363,16 +363,15 @@
     background-color    : rgb(250, 250, 245);
 }*/
 
-variantboolean>checkbox
+variantboolean>hbox>checkbox
 {
     -moz-box-flex       : 1;
 }
 variantboolean
 {
-    -moz-box-orient     : horizontal;
-    -moz-box-flex       : 1;    
+    -moz-box-orient     : vertical;
 }
-variantboolean>spacer
+variantboolean>hbox>spacer
 {
     -moz-box-flex       : 1;    
 }
Index: mas/mas.m
===================================================================
RCS file: /var/cvs/map/mas/mas/mas.m,v
retrieving revision 1.20
diff -u -r1.20 mas.m
--- mas/mas.m	2005/01/07 08:56:14	1.20
+++ mas/mas.m	2005/01/07 15:51:42
@@ -135,6 +135,13 @@
 :- type role_map == map(string, mas.types.role).
 */
 
+    %
+    % Is something available, if not the multi-lingual reason why not.
+    %
+:- type available
+    --->    yes
+    ;       no(text).
+
 %------------------------------------------------------------------------------%
 
 risk_objects_xbl(S, _Mas, !IO) :-
@@ -281,7 +288,7 @@
 applicable_products(Mas, Session, Risks) = Products :-
     AllProducts = map__values(Mas ^ products),
     list__filter(applicable_product(Mas, Risks), AllProducts, Products0),
-    Session = tariffication(_Risks, _Roles, IParties, _Selection, Filter),
+    Session = tariffication(_Risks, _Roles, _IParties, _Selection, Filter),
     Products = apply_filter_for_products(Filter, Products0).
 
 :- pred applicable_product(mas::in, list(risk)::in, product::in) is semidet.
@@ -1090,7 +1097,7 @@
 
 shopper_screen_xbl(S, Mas, Session, Febiac, Config, !IO) :-
         % XXX The products should be passed to this predicate.
-    Session = tariffication(Risks, _Roles, _IParties, _, Filter),
+    Session = tariffication(Risks, _Roles, _IParties, _, _Filter),
     Selection = get_product_risk_coverage_selection_for_shopper_screen(Mas,
             Session, Risks),
 
@@ -1253,7 +1260,7 @@
                 ::(pred(in, in, in, in, out, di, uo) is det),
                 table::out, io::di, io::uo) is det.
 
-get_multi_tarifficaton_table(Mas, _Session, _Febiac, _Config,
+get_multi_tarifficaton_table(Mas, Session, _Febiac, _Config,
                 Selection, TariffCoverage, Table, !IO) :-
     % Session = tariffication(Risks, _Roles, _IParties, _Selection),
     Risks = list__remove_dups(
@@ -1263,7 +1270,7 @@
     Products = assoc_list__keys(Selection),
     
         % Tariff each product giving a column, if needed.
-    list__map_foldl(tariff_product(Mas, Risks, Selection, TariffCoverage), 
+    list__map_foldl(tariff_product(Mas, Session, Risks, Selection, TariffCoverage), 
             Products, ProdColumns, !IO),
 
     Columns = [row_titles(Mas, Risks) | ProdColumns],
@@ -1299,16 +1306,16 @@
     % where each cell contains the premiums for that risk object in
     % that product, if applicable.
     %
-:- pred tariff_product(mas::in, list(risk)::in, 
+:- pred tariff_product(mas::in, session::in, list(risk)::in, 
                 product_risk_coverage_selection::in,
                 pred(product, risk, coverage, selected_coverage, element, io, io)
                 ::(pred(in, in, in, in, out, di, uo) is det),
                 product::in, column::out, io::di, io::uo) is det.
 
-tariff_product(Mas, Risks, Selection, TariffCoverage, Product, Column, !IO) :-
+tariff_product(Mas, Session, Risks, Selection, TariffCoverage, Product, Column, !IO) :-
     ( assoc_list__search(Selection, Product, SelectedRisks) ->
         list__map_foldl(
-                tariff_risk(Mas, Product, SelectedRisks, TariffCoverage),
+                tariff_risk(Mas, Product, SelectedRisks, TariffCoverage, Session),
                 Risks, MaybeCells, !IO),
          Cells = list__map(get_cell_from_maybe_cell, MaybeCells),
          Column = column([title_cell(Product) | Cells])
@@ -1319,24 +1326,49 @@
 :- pred tariff_risk(mas::in, product::in, risk_coverage_selection::in, 
                 pred(product, risk, coverage, selected_coverage, element, io, io)
                 ::(pred(in, in, in, in, out, di, uo) is det),
-                risk::in, maybe(cell)::out, io::di, io::uo) is det.
+                session::in, risk::in, maybe(cell)::out, io::di, io::uo) is det.
 
-tariff_risk(_Mas, Product,
-                SelectedRisks, TariffCoverage, Risk, MaybeCell, !IO) :-
-    ( assoc_list__search(SelectedRisks, Risk, SelectedCoverages) ->
-        P = (pred((C-SC)::in, LIn::in, LOut::out, !.IO::di, !:IO::uo) is det :-
-            TariffCoverage(Product, Risk, C, SC, F, !IO),
-            LOut = [F | LIn]
-        ),
-        list__foldl2(P, SelectedCoverages, [], Fs, !IO)
-    ;
-        Fs = []
+tariff_risk(Mas, Product,
+                SelectedRisks, TariffCoverage, Session, Risk, MaybeCell, !IO) :-
+
+    ProductRisk = Mas ^ product_risk(Product, Risk),
+    Latest = ProductRisk ^ last_version,
+    PRV = Mas ^ product_risk_version(Latest),
+
+    RiskPlus = risk_plus(Mas, Session, Product, Risk),
+    Available = answer_all_mandatory_attributes(Mas, PRV, RiskPlus, []),
+    ( Available = yes,
+        ( assoc_list__search(SelectedRisks, Risk, SelectedCoverages) ->
+            P = (pred((C-SC)::in, LIn::in, LOut::out, !.IO::di, !:IO::uo) is det :-
+                TariffCoverage(Product, Risk, C, SC, F, !IO),
+                LOut = [F | LIn]
+            ),
+            list__foldl2(P, SelectedCoverages, [], Fs, !IO)
+        ;
+            Fs = []
+        )
+    ; Available = no(Reason),
+        Id = "XXX",
+        Text = multi("", "", "", "") `app`
+                label("Need answers for ") `app` Reason,
+        Type = none,
+        DataId = no,
+        Init = no,
+        Action = no,
+        Errs = [],
+        Field = field(Id, Text, Type, DataId, Init, Action, Errs),
+        Fs = [field(Field)]
     ),
     ( Fs = [] ->
         MaybeCell = no
     ;
         MaybeCell = yes(cell(Fs))
     ).
 
 :- func get_cell_from_maybe_cell(maybe(cell)) = cell.
 
@@ -1397,32 +1429,44 @@
         ), UnsortedVariants),
 
     RiskPlus = risk_plus(Mas, Session, Product, Risk),
-    ( is_coverage_available(Mas, Product, RiskPlus, Coverage) ->
-        Action = no,
-        Init = coverage_init_javascript(Risk, Coverage),
+    CoverageAvailable = is_coverage_available(Mas, Product, RiskPlus, Coverage),
+    Action = no,
+    ( CoverageAvailable = yes,
+        ProductRisk = Mas ^ product_risk(Product, Risk),
+        Latest = ProductRisk ^ last_version,
+        PRV = Mas ^ product_risk_version(Latest),
+
         ( Variants = [],
+            Init = coverage_init_javascript(Risk, Coverage),
             Price = 10.0,
-            Type = variant_boolean(Price)
+            Type = variant_boolean(Price),
+            Errs = []
         ; Variants = [_ | _],
-            list__map_foldl(tariff_variant(Mas, Risk), Variants, Choices, !IO),
-            Type = variant_mchoice(Choices)
+            Init = coverage_init_javascript(Risk, Coverage),
+            list__map_foldl(tariff_variant(Mas, PRV, RiskPlus), Variants, Choices, !IO),
+            Type = variant_mchoice(Choices),
+            Errs = []
         )
-    ;
-        Action = yes(initialization("this.disable();")),
-        Init = no,
+
+        % XXX place the reason in an informational box.
+    ; CoverageAvailable = no(Reason),
+        Init = yes(initialization("this.disable();")),
         ( Variants = [],
             Price = 0.0,
             Type = variant_boolean(Price)
         ; Variants = [_ | _],
             list__map_foldl(disabled_variant(Mas, Risk), Variants, Choices, !IO),
             Type = variant_mchoice(Choices)
-        )
-    ),
+        ),
 
-    Errs = [],
+            % XXX hack to display the reason.
+        Message = replace_all(string(Reason), "'", ""),
+        ErrInit = "this.setAttribute('tooltiptext', '" ++ Message ++ "');",
+        Errs = [validation("XXX_Reason", expression("true"),
+                initialization(ErrInit), label("Missing attributes"))]
+    ),
     Field = field(Id, Text, Type, DataId, Init, Action, Errs). % XXX XXX XXX
 
-
     %
     % A coverage is available if all of the attributes required for a coverage
     % have been answered.
@@ -1431,15 +1475,25 @@
     % a risk or a role, as these are the only attributes which are available at
     % this point on the shopper screen.
     %
-:- pred is_coverage_available(mas::in, product::in, risk_plus::in, coverage::in) is semidet.
+:- func is_coverage_available(mas, product, risk_plus, coverage) = available.
 
-is_coverage_available(Mas, Product, RiskPlus, Coverage) :-
+is_coverage_available(Mas, Product, RiskPlus, Coverage) = Available :-
     AllAttrs = risk_plus_attributes(RiskPlus),
     CovAttrs = coverage_attributes(Mas, Product, RiskPlus ^ risk, Coverage),
 
         % The attributes associated with the coverage must be a subset
         % of the attributes we have given answers for.
-    set(CovAttrs) `subset` set(AllAttrs).
+    ( set(CovAttrs) `subset` set(AllAttrs) ->
+        Available = yes
+    ;
+            % XXX this reason needs to be made
+            %   - multi-lingual
+            %   - useful text to refer to the attribute
+        Missing = list(set(CovAttrs) `difference` set(AllAttrs)),
+        S = append_list(map(func(X) = X ^ id ++ " ", Missing)),
+        Reason = label(S),
+        Available = no(Reason)
+    ).
 
 
     %
@@ -1519,24 +1573,34 @@
         ), Mas ^ rate_unit(Id) ^ rate_unit_attrs, Attrs).
 
 
-:- pred tariff_variant(mas::in, risk::in, variant::in,
+:- pred tariff_variant(mas::in, product_risk_version::in,
+                risk_plus::in, variant::in,
                 variant_choice::out, io::di, io::uo) is det.
 
-tariff_variant(_Mas, Risk, Variant, Choice, !IO) :-
-    Id = Variant ^ variant_id ^ id ++ "_" ++ Risk ^ risk_id,
+tariff_variant(_Mas, _PRV, RiskPlus, Variant, Choice, !IO) :-
+    Id = Variant ^ variant_id ^ id ++ "_" ++ RiskPlus ^ risk ^ risk_id,
     Text = Variant ^ variant_name,
+    Disabled = no,
     Price = 20.0,
-    Choice = vchoice(Id, Text, Price).
+    Choice = vchoice(Id, Text, Disabled, Price).
 
+:- func value(mas, types.value_id) = session.value.
 
+value(Mas, Id) = value(Attr, Val) :-
+    V = Mas ^ value(Id),
+    Attr = V ^ value_attribute ^ id,
+    C = Mas ^ constant(V ^ value_value),
+    C = constant(_, _, Val).
+
 :- pred disabled_variant(mas::in, risk::in, variant::in,
                 variant_choice::out, io::di, io::uo) is det.
 
 disabled_variant(_Mas, Risk, Variant, Choice, !IO) :-
     Id = Variant ^ variant_id ^ id ++ "_" ++ Risk ^ risk_id,
     Text = Variant ^ variant_name,
+    Disabled = yes,
     Price = 0.0,
-    Choice = vchoice(Id, Text, Price).
+    Choice = vchoice(Id, Text, Disabled, Price).
 
     %
     % Coverages are only available depending on whether or not other
@@ -1646,7 +1710,13 @@
     ;
         AssocRoles = AssocRoles0
     ),
-    RiskPlus = risk_plus(Risk, AssocRoles).
+
+        %
+        % XXX add VERDEFF because we don't handle this special 
+        % variable yet.
+        %
+    NewValues = [value("VERDEFF", "01/01/2001") | Risk ^ risk_values],
+    RiskPlus = risk_plus(Risk ^ risk_values := NewValues, AssocRoles).
 
     %
     % Given a risk, find the associated role if it exists.
@@ -1674,6 +1744,59 @@
 
 %------------------------------------------------------------------------------%
 
+    %
+    % Does the current risk answer all the mandatory questions for the
+    % given product risk version?
+    %
+:- func answer_all_mandatory_attributes(mas,
+                product_risk_version, risk_plus,
+                list(session.value)) = available.
+
+answer_all_mandatory_attributes(Mas, PRV, RiskPlus, Values) = Available :-
+    AllAttrs = list__map(func(V) = attribute_id(V ^ attr_id), Values) ++
+                    risk_plus_attributes(RiskPlus),
+    MandatoryAttrs = mandatory_attributes(Mas, PRV),
+
+    ( set(MandatoryAttrs) `subset` set(AllAttrs) ->
+        Available = yes
+    ;
+            % XXX this reason needs to be made
+            %   - multi-lingual
+            %   - useful text to refer to the attribute
+        Missing = list(set(MandatoryAttrs) `difference` set(AllAttrs)),
+        S = append_list(map(func(X) = X ^ id ++ " ", Missing)),
+        Reason = label(S),
+        Available = no(Reason)
+    ).
+    
+
+    %
+    % Find all the attributes which must have an answer to tariff
+    % a product_risk_version.
+    %
+:- func mandatory_attributes(mas, product_risk_version) = list(attribute_id).
+
+mandatory_attributes(Mas, ProductRiskVersion) = Attributes :-
+
+        % Find all the attributes which are possibly required
+        % for each coverage.
+    Coverages = list__map(func(I) = Mas ^ coverage(I), ProductRiskVersion ^ prv_coverages),
+    AllRateUnitIds = condense(map(func(C) = C ^ coverage_rateunits, Coverages)),
+    CAttrs = condense(map(func(R) = Mas ^ rate_unit(R) ^ rate_unit_attrs, AllRateUnitIds)),
+
+        % Find all the attributes which are required for
+        % tariffication.
+    list__filter_map(
+            is_activity_question(Mas ^ questions, activity_id("tariffication")),
+            ProductRiskVersion ^ prv_questions, TQuestions),
+    TAttrs = list__map(func(Q) = Q ^ q_attribute, TQuestions),
+
+        % An attribute is mandatory if it is required for tariffication,
+        % but not possibly required for a coverage.
+    Attributes = list(set(TAttrs) `difference` set(CAttrs)).
+
+%------------------------------------------------------------------------------%
+
 
 /*
     Session = tariffication(RiskObjects0, Roles, IParties),
@@ -2429,7 +2552,8 @@
 
 %------------------------------------------------------------------------------%
 %------------------------------------------------------------------------------%
-risk_type_product_selection_xbl(S, Mas, Session, Config, !IO) :-
+
+risk_type_product_selection_xbl(S, Mas, _Session, _Config, !IO) :-
     Risks = map__values(Mas ^ risk_objects),
     map__values(Mas ^ products, Products),
     RiskQuestionBox = risk_types_box(Risks),
Index: mas/mas.screen.m
===================================================================
RCS file: /var/cvs/map/mas/mas/mas.screen.m,v
retrieving revision 1.10
diff -u -r1.10 mas.screen.m
--- mas/mas.screen.m	2005/01/05 16:05:08	1.10
+++ mas/mas.screen.m	2005/01/07 15:51:42
@@ -280,9 +280,10 @@
  */
 :- type variant_choice
         --->    vchoice(
-                    vmchoice_id     :: string,
-                    vmchoice_text   :: text,
-                    vmchoice_price  :: float
+                    vmchoice_id         :: string,
+                    vmchoice_text       :: text,
+                    vmchoice_disabled   :: bool,
+                    vmchoice_price      :: float
                 ).
 /*****/
 
Index: mas/mas.xbl.m
===================================================================
RCS file: /var/cvs/map/mas/mas/mas.xbl.m,v
retrieving revision 1.17
diff -u -r1.17 mas.xbl.m
--- mas/mas.xbl.m	2005/01/06 15:00:03	1.17
+++ mas/mas.xbl.m	2005/01/07 15:51:42
@@ -473,9 +473,14 @@
 
     Ident = " id=\"" ++ Choice ^ vmchoice_id ++ "\"",
     Name = name_to_attributes(Choice ^ vmchoice_text),
+    ( Choice ^ vmchoice_disabled = yes,
+        Disabled = " disable=\"true\""
+    ; Choice ^ vmchoice_disabled = no,
+        Disabled = " disable=\"false\""
+    ),
     Price = " price=\"" ++ float_to_currency_string(Amt) ++ "\"",
 
-    Attributes = Ident ++ Name ++ Price,
+    Attributes = Ident ++ Name ++ Disabled ++ Price,
 
     stream__write_strings(S, [
             indent(I),  "<variantchoice", Attributes, "/>\n"
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list