basing everything on variable nodeset

This commit is contained in:
skyanth 2019-06-20 14:57:55 +02:00
parent c65cc36910
commit 703e769545
10 changed files with 577 additions and 215 deletions

View File

@ -6,6 +6,7 @@
schemaLocation="http://www.w3.org/2001/xml.xsd"/> schemaLocation="http://www.w3.org/2001/xml.xsd"/>
<xs:import namespace="http://www.w3.org/2001/XInclude" <xs:import namespace="http://www.w3.org/2001/XInclude"
schemaLocation="http://www.w3.org/2001/XInclude/XInclude.xsd"/> schemaLocation="http://www.w3.org/2001/XInclude/XInclude.xsd"/>
<xs:include schemaLocation="servicebreakdown.xsd"/>
<xs:include schemaLocation="common.xsd"/> <xs:include schemaLocation="common.xsd"/>
<xs:element name="offerte"> <xs:element name="offerte">
@ -46,7 +47,7 @@
<xs:element name="activityinfo"> <xs:element name="activityinfo">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:all>
<xs:element ref="duration" minOccurs="1"/> <xs:element ref="duration" minOccurs="1"/>
<xs:element ref="persondays" minOccurs="1"/> <xs:element ref="persondays" minOccurs="1"/>
<xs:element ref="planning" minOccurs="1"/> <xs:element ref="planning" minOccurs="1"/>
@ -59,10 +60,11 @@
<xs:element ref="technical_artefact_analysis" minOccurs="0"/> <xs:element ref="technical_artefact_analysis" minOccurs="0"/>
<xs:element minOccurs="0" ref="target_application"/> <xs:element minOccurs="0" ref="target_application"/>
<xs:element minOccurs="0" ref="target_application_producer"/> <xs:element minOccurs="0" ref="target_application_producer"/>
</xs:sequence> <xs:element ref="breakdown" minOccurs="0"/>
</xs:all>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="organizational_readiness_assessment"> <xs:element name="organizational_readiness_assessment">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
@ -71,7 +73,7 @@
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="team"> <xs:element name="team">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
@ -79,7 +81,7 @@
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="member"> <xs:element name="member">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
@ -88,34 +90,17 @@
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="expertise" type="xs:string"/> <xs:element name="expertise" type="xs:string"/>
<xs:element name="security_incident_management" type="ir_service"/> <xs:element name="security_incident_management" type="ir_service"/>
<xs:element name="technical_artefact_analysis" type="ir_service"/> <xs:element name="technical_artefact_analysis" type="ir_service"/>
<xs:complexType name="ir_service"> <xs:complexType name="ir_service">
<xs:sequence> <xs:sequence>
<xs:element ref="rate"/> <xs:element ref="rate"/>
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
<xs:element name="fee">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:integer">
<xs:attribute name="denomination" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="eur"/>
<xs:enumeration value="gbp"/>
<xs:enumeration value="usd"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="annex"> <xs:element name="annex">
<xs:complexType> <xs:complexType>
@ -203,6 +188,18 @@
<xs:element ref="contact"/> <xs:element ref="contact"/>
<xs:element ref="generate_targets"/> <xs:element ref="generate_targets"/>
<xs:element name="generate_teammembers"/> <xs:element name="generate_teammembers"/>
<xs:element name="generate_service_breakdown">
<xs:complexType>
<xs:attribute name="format" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="list"/>
<xs:enumeration value="table"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element ref="generate_offer_signature_box"/> <xs:element ref="generate_offer_signature_box"/>
</xs:choice> </xs:choice>
</xs:sequence> </xs:sequence>

View File

@ -114,6 +114,7 @@
<xs:element ref="name"/> <xs:element ref="name"/>
<xs:element ref="bio"/> <xs:element ref="bio"/>
</xs:sequence> </xs:sequence>
<xs:attributeGroup ref="xml:specialAttrs"/>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
@ -289,8 +290,8 @@
<xs:element ref="recommendation_summary"/> <xs:element ref="recommendation_summary"/>
</xs:choice> </xs:choice>
</xs:sequence> </xs:sequence>
<xs:attribute ref="xml:base"/>
<xs:attribute ref="xml:lang"/> <xs:attribute ref="xml:lang"/>
<xs:attribute name="id" use="required" type="xs:ID"/>
<xs:attribute ref="threatLevel" use="optional" default="N/A"/> <xs:attribute ref="threatLevel" use="optional" default="N/A"/>
<xs:attribute name="status" use="optional"> <xs:attribute name="status" use="optional">
<xs:simpleType> <xs:simpleType>
@ -311,7 +312,6 @@
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:attribute> </xs:attribute>
<xs:attribute ref="xml:base"/>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="description"> <xs:element name="description">

View File

@ -38,28 +38,30 @@
</targets> </targets>
<!-- How long would you like the test to be? (in days) --> <!-- How long would you like the test to be? (in days) -->
<days>0</days> <days>0</days>
<!-- How many persondays (if you don't know, try days * number of assigned pentesters) --> <!-- How many persondays -->
<persondays>0</persondays> <persondays>0</persondays>
<!-- LAAT PERSONDAYS OP 0 STAAN OM AUTOMATISCH TE LATEN BEREKENEN VIA SERVICE BREAKDOWN -->
<!-- Service execution (Use one of the following values: time-boxed, subscription) --> <!-- Service execution (Use one of the following values: time-boxed, subscription) -->
<nature>time-boxed</nature> <nature>time-boxed</nature>
<!-- Testing type (Use one of the following values: crystal-box, black-box, grey-box) --> <!-- Testing type (Use one of the following values: crystal-box, black-box, grey-box) -->
<type>crystal-box</type> <type>crystal-box</type>
<!-- Test planning (when would you like the test to be executed --> <!-- Test planning (when would you like the test to be executed -->
<!-- dates should be in ISO format (YYY-MM-DD) --> <!-- dates should be in ISO format (YYYY-MM-DD) -->
<!-- if unknown, write TBD --> <!-- if unknown, write TBD -->
<planning><start>YYYY-MM-DD</start><end>TBD</end></planning> <planning><start>YYYY-MM-DD</start><end>TBD</end></planning>
<!-- Pentest report delivery date (please allow at least 1 week between the end of the pentest and the report delivery date) --> <!-- Pentest report delivery date (please allow at least 1 week between the end of the pentest and the report delivery date) -->
<!-- date should be in ISO format (YYY-MM-DD) --> <!-- date should be in ISO format (YYYY-MM-DD) -->
<!-- if unknown, write TBD --> <!-- if unknown, write TBD -->
<delivery>TBD</delivery> <delivery>TBD</delivery>
<!-- Do you need/want a code audit? (possible values: yes/no), only for pentest --> <!-- Do you need/want an additional code audit? (possible values: yes/no), only for pentest -->
<codeaudit perform="yes"/> <codeaudit perform="yes"/>
<!-- Is there an application that needs to be tested? Add an <application_name> element below. --> <!-- Is there an application that needs to be tested? Add an <application_name> element below. -->
<!-- INSERT OPTIONAL APPLICATION NAME HERE --> <!-- INSERT OPTIONAL APPLICATION NAME HERE -->
<!-- ___________________________________ --> <!-- <application_name>AppToTest</application_name> -->
<!-- rate (to be filled in by ROS ;) --> <!-- rate (to be filled in by ROS ;) -->
<rate>0</rate> <rate>0</rate>
<!-- LAAT RATE OP 0 STAAN OM FEE AUTOMATISCH TE LATEN BEREKENEN VIA SERVICE BREAKDOWN -->
</activityinfo> </activityinfo>
</quickscope> </quickscope>

View File

@ -1,39 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<service_list> <breakdown xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../dtd/servicebreakdown.xsd">
<service> <service>
<description>Determine and set up attack vectors</description> <description>Example Service 1: set duration in days and with hourly rate.</description>
<duration in="days">2</duration> <effort in="days">2</effort>
<hourly_rate vat="excl" denomination="eur">1</hourly_rate> <hourly_rate>10</hourly_rate>
<fee> <fee denomination="eur">
<computed/> <computed/>
</fee> </fee>
</service> </service>
<service> <service>
<description>Set up infrastructure and support</description> <description>Example Service 2: variable duration with min/max parameters and with hourly
<duration in="hours">20</duration> rate.</description>
<hourly_rate vat="excl" denomination="eur">2</hourly_rate> <effort in="days">
<fee> <min>3</min>
<max>4</max>
</effort>
<hourly_rate>10</hourly_rate>
<fee denomination="eur">
<computed/> <computed/>
</fee> </fee>
</service> </service>
<service> <service>
<description>Attacking and reporting</description> <description>Example Service 3: set duration in days with CUSTOM (non-computed) set
<duration in="days">5</duration> fee.</description>
<hourly_rate vat="excl" denomination="eur">3</hourly_rate> <effort in="days">5</effort>
<fee> <fee denomination="eur">500</fee>
<computed/> </service>
<service>
<description>Example Service 4: set duration in hours with CUSTOM (non-computed) variable fee
(min/max).</description>
<effort in="hours">4</effort>
<fee denomination="eur">
<min>100</min>
<max>200</max>
</fee> </fee>
</service> </service>
<service> <service>
<description>Travel and hotel</description> <description>Example Service 5: set duration in days with CUSTOM (non-computed) estimated
<fee vat="excl" denomination="eur">50</fee> fee.</description>
<effort in="hours">4</effort>
<fee denomination="eur" estimate="yes">1000</fee>
</service> </service>
<service> <service optional="yes">
<description>Optional: presentation of findings</description> <description>Example Service 6: optional service</description>
<duration in="days"><min>0</min><max>2</max></duration> <effort in="days">
<hourly_rate vat="incl" denomination="eur">100</hourly_rate> <min>1</min>
<fee> <max>2</max>
</effort>
<hourly_rate>50</hourly_rate>
<fee denomination="eur">
<computed/> <computed/>
</fee> </fee>
</service> </service>
</service_list> <extra>
<description>Example Extra Cost 1: set fee</description>
<fee denomination="eur">1000</fee>
</extra>
<extra>
<description>Example Extra Cost 2: variable min/max fee</description>
<fee denomination="eur">
<min>1000</min>
<max>1200</max>
</fee>
</extra>
<extra>
<description>Example Extra Cost 3: estimated fee</description>
<fee denomination="eur" estimate="yes">600</fee>
</extra>
<extra>
<description>Example Extra Cost 4: with duration</description>
<effort in="days">6</effort>
<fee denomination="eur">600</fee>
</extra>
</breakdown>

View File

@ -6,10 +6,12 @@
</p> </p>
<ul> <ul>
<li><company_short/> performs a <p_duration/>-day <company_svc_short/> starting <p_startdate/>.</li> <li><company_short/> performs a <p_duration/>-day <company_svc_short/> starting <p_startdate/>.</li>
<li><company_short/> delivers the final report on <p_reportdue/>.</li> <li><company_short/> delivers the final report on
<p_reportdue/>.</li>
</ul> </ul>
<p> <p>
Our fixed-fee price quote for the above described <company_svc_short/> is <p_fee/>.- Our fixed-fee price quote for the above described <company_svc_short/> is
<p_fee/>
excl. VAT and out-of-pocket expenses. excl. VAT and out-of-pocket expenses.
<company_short/> will send an invoice after the completion of this assignment. <company_short/> will send an invoice after the completion of this assignment.
<client_short/> will pay the agreed amount within 14 days of the invoice date. <client_short/> will pay the agreed amount within 14 days of the invoice date.

View File

@ -461,8 +461,8 @@
<xsl:choose> <xsl:choose>
<xsl:when test="@format = 'list'"> <xsl:when test="@format = 'list'">
<fo:list-block xsl:use-attribute-sets="list"> <fo:list-block xsl:use-attribute-sets="list">
<xsl:for-each select="//service_list/service"> <xsl:for-each select="$serviceNodeSet/entry[@type = 'service']">
<xsl:if test="duration"> <xsl:if test="d">
<fo:list-item xsl:use-attribute-sets="li"> <fo:list-item xsl:use-attribute-sets="li">
<!-- insert a bullet --> <!-- insert a bullet -->
<fo:list-item-label end-indent="label-end()"> <fo:list-item-label end-indent="label-end()">
@ -473,31 +473,26 @@
<!-- list text --> <!-- list text -->
<fo:list-item-body start-indent="body-start()"> <fo:list-item-body start-indent="body-start()">
<fo:block> <fo:block>
<xsl:value-of select="description"/> <xsl:value-of select="desc"/>
<xsl:text>: </xsl:text> <xsl:text>: </xsl:text>
<xsl:value-of select="duration"/> <xsl:value-of select="d"/>
<xsl:text> </xsl:text>
<xsl:value-of select="duration/@in"/>
</fo:block> </fo:block>
</fo:list-item-body> </fo:list-item-body>
</fo:list-item> </fo:list-item>
</xsl:if> </xsl:if>
</xsl:for-each> </xsl:for-each>
</fo:list-block> </fo:list-block>
<xsl:call-template name="displayErrorText">
<xsl:with-param name="string">TODO: total!</xsl:with-param>
</xsl:call-template>
</xsl:when> </xsl:when>
<xsl:when test="@format = 'table'"> <xsl:when test="@format = 'table'">
<fo:block> <fo:block>
<fo:table xsl:use-attribute-sets="fwtable borders"> <fo:table xsl:use-attribute-sets="fwtable borders">
<fo:table-column column-width="proportional-column-width(70)" <fo:table-column column-width="proportional-column-width(6)"
xsl:use-attribute-sets="borders"/> xsl:use-attribute-sets="borders"/>
<fo:table-column column-width="proportional-column-width(10)" <fo:table-column column-width="proportional-column-width(2)"
xsl:use-attribute-sets="borders"/> xsl:use-attribute-sets="borders"/>
<fo:table-column column-width="proportional-column-width(10)" <fo:table-column column-width="proportional-column-width(3)"
xsl:use-attribute-sets="borders"/> xsl:use-attribute-sets="borders"/>
<fo:table-column column-width="proportional-column-width(10)" <fo:table-column column-width="proportional-column-width(4)"
xsl:use-attribute-sets="borders"/> xsl:use-attribute-sets="borders"/>
<fo:table-body> <fo:table-body>
<fo:table-row> <fo:table-row>
@ -505,7 +500,7 @@
<fo:block> Description </fo:block> <fo:block> Description </fo:block>
</fo:table-cell> </fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="th"> <fo:table-cell xsl:use-attribute-sets="th">
<fo:block> Duration </fo:block> <fo:block> Effort </fo:block>
</fo:table-cell> </fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="th"> <fo:table-cell xsl:use-attribute-sets="th">
<fo:block> Hourly rate </fo:block> <fo:block> Hourly rate </fo:block>
@ -514,84 +509,107 @@
<fo:block> Fee </fo:block> <fo:block> Fee </fo:block>
</fo:table-cell> </fo:table-cell>
</fo:table-row> </fo:table-row>
<xsl:for-each select="//service_list/service"> <xsl:for-each select="$serviceNodeSet/entry">
<fo:table-row> <fo:table-row>
<fo:table-cell xsl:use-attribute-sets="td"> <xsl:if test="position() mod 2 != 0">
<fo:block> <xsl:attribute name="background-color"
<xsl:value-of select="description"/> >#ededed</xsl:attribute>
</fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="td">
<xsl:choose>
<xsl:when test="duration and duration/@in">
<fo:block>
<xsl:value-of select="duration"/>
<xsl:text> </xsl:text>
<xsl:value-of select="duration/@in"/>
</fo:block>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="number-columns-spanned"
>2</xsl:attribute>
<fo:block>(flat rate)</fo:block>
</xsl:otherwise>
</xsl:choose>
</fo:table-cell>
<xsl:if test="duration and hourly_rate">
<fo:table-cell xsl:use-attribute-sets="td">
<fo:block>
<xsl:call-template name="getDenomination">
<xsl:with-param name="placeholderElement"
select="hourly_rate"/>
</xsl:call-template>
<xsl:value-of select="hourly_rate"/>
</fo:block>
</fo:table-cell>
</xsl:if> </xsl:if>
<fo:table-cell xsl:use-attribute-sets="td"> <fo:table-cell xsl:use-attribute-sets="td">
<xsl:if
test="not(normalize-space(d)) and not(normalize-space(h))">
<xsl:attribute name="number-columns-spanned"
>3</xsl:attribute>
</xsl:if>
<fo:block>
<xsl:value-of select="desc"/>
</fo:block>
</fo:table-cell>
<xsl:if test="d">
<fo:table-cell xsl:use-attribute-sets="td">
<fo:block>
<xsl:value-of select="d"/>
</fo:block>
</fo:table-cell>
<xsl:choose> <xsl:choose>
<xsl:when test="not(fee/computed)"> <xsl:when test="normalize-space(h)">
<!-- hardcoded fee, we'll need a denomination --> <fo:table-cell xsl:use-attribute-sets="td">
<fo:block xsl:use-attribute-sets="moneycell"> <fo:block text-align="right">
<xsl:call-template name="getDenomination"> <xsl:call-template name="getDenomination">
<xsl:with-param name="placeholderElement" <xsl:with-param name="placeholderElement"
select="fee"/> select="."/>
</xsl:call-template> </xsl:call-template>
<fo:leader leader-pattern="space"/> <xsl:call-template name="prettyMissingDecimal">
<xsl:value-of select="fee"/> <xsl:with-param name="n" select="h"/>
</fo:block> </xsl:call-template>
<xsl:text> excl. VAT</xsl:text>
</fo:block>
</fo:table-cell>
</xsl:when> </xsl:when>
<xsl:otherwise> <xsl:otherwise>
<!-- computed fee; compute using duration and use hourly rate denomination --> <fo:table-cell xsl:use-attribute-sets="td">
<fo:block xsl:use-attribute-sets="moneycell"> <fo:block text-align="right">-</fo:block>
<xsl:call-template name="getDenomination"> </fo:table-cell>
<xsl:with-param name="placeholderElement"
select="hourly_rate"/>
</xsl:call-template>
<fo:leader leader-pattern="space"/>
<xsl:choose>
<xsl:when test="duration/@in = 'hours'">
<!-- multiply with hourly rate -->
<xsl:value-of select="duration * hourly_rate"/>
</xsl:when>
<xsl:when test="duration/@in = 'days'">
<!-- multiply with hourly rate * 8 -->
<xsl:value-of select="duration * hourly_rate * 8"
/>
</xsl:when>
</xsl:choose>
</fo:block>
</xsl:otherwise> </xsl:otherwise>
</xsl:choose> </xsl:choose>
</xsl:if>
<fo:table-cell xsl:use-attribute-sets="td">
<fo:block text-align="right">
<xsl:choose>
<xsl:when test="not(f/min = f/max)">
<xsl:call-template name="getDenomination">
<xsl:with-param name="placeholderElement"
select="."/>
</xsl:call-template>
<xsl:value-of select="f/min"/>
<xsl:text> - </xsl:text>
<xsl:call-template name="getDenomination">
<xsl:with-param name="placeholderElement"
select="."/>
</xsl:call-template>
<xsl:call-template name="prettyMissingDecimal">
<xsl:with-param name="n" select="f/max"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="getDenomination">
<xsl:with-param name="placeholderElement"
select="."/>
</xsl:call-template>
<xsl:call-template name="prettyMissingDecimal">
<xsl:with-param name="n" select="f/min"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
<xsl:text> excl. VAT</xsl:text>
<xsl:if test="@estimate = true()">*</xsl:if>
</fo:block>
</fo:table-cell> </fo:table-cell>
</fo:table-row> </fo:table-row>
</xsl:for-each> </xsl:for-each>
<fo:table-row xsl:use-attribute-sets="totalRow">
<fo:table-cell number-columns-spanned="4"
xsl:use-attribute-sets="td">
<fo:block xsl:use-attribute-sets="totalcell">
<xsl:text>Total</xsl:text>
<xsl:if test="$serviceNodeSet/entry/@estimate">
(estimate)</xsl:if>
<xsl:text>:</xsl:text>
<fo:leader leader-pattern="space"/>
<xsl:call-template name="calculateTotal"/>
<xsl:text> excl. VAT</xsl:text>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body> </fo:table-body>
</fo:table> </fo:table>
</fo:block> </fo:block>
<xsl:call-template name="displayErrorText">
<xsl:with-param name="string">TODO total</xsl:with-param> <xsl:if test="$serviceNodeSet/entry/@estimate = true()">
</xsl:call-template> <fo:block text-align="right">
<xsl:text>* Estimate</xsl:text>
</fo:block>
</xsl:if>
</xsl:when> </xsl:when>
<xsl:otherwise> <xsl:otherwise>
<xsl:call-template name="displayErrorText"> <xsl:call-template name="displayErrorText">
@ -602,4 +620,94 @@
</xsl:choose> </xsl:choose>
</xsl:template> </xsl:template>
<xsl:template name="calculateTotal">
<xsl:param name="denoms" tunnel="yes">
<xsl:for-each-group select="$serviceNodeSet/entry" group-by="@denomination">
<denom denomination="{current-grouping-key()}"/>
</xsl:for-each-group>
</xsl:param>
<xsl:variable name="allDenominationsAreEqual" select="count($denoms/denom) = 1"/>
<xsl:variable name="minmaxesPresent"
select="boolean($serviceNodeSet/entry/f/min and $serviceNodeSet/entry/f/max)"/>
<xsl:variable name="estimatePresent" select="$serviceNodeSet/entry/@estimate"/>
<xsl:variable name="totalMinFees" select="sum($serviceNodeSet/entry/f/min)"/>
<xsl:variable name="totalMaxFees" select="sum($serviceNodeSet/entry/f/max)"/>
<xsl:choose>
<xsl:when test="not($totalMinFees = $totalMaxFees)">
<!-- We have different min and max fees, print range -->
<xsl:call-template name="checkDenomination">
<xsl:with-param name="allDenominationsAreEqual"
select="$allDenominationsAreEqual"/>
<xsl:with-param name="denoms" select="$denoms"/>
</xsl:call-template>
<xsl:value-of select="$totalMinFees"/>
<xsl:text> - </xsl:text>
<xsl:call-template name="checkDenomination">
<xsl:with-param name="allDenominationsAreEqual"
select="$allDenominationsAreEqual"/>
<xsl:with-param name="denoms" select="$denoms"/>
</xsl:call-template>
<xsl:call-template name="prettyMissingDecimal">
<xsl:with-param name="n" select="$totalMaxFees"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- Min and max are equal; print single price -->
<xsl:call-template name="checkDenomination">
<xsl:with-param name="allDenominationsAreEqual"
select="$allDenominationsAreEqual"/>
<xsl:with-param name="denoms" select="$denoms"/>
</xsl:call-template>
<xsl:call-template name="prettyMissingDecimal">
<xsl:with-param name="n" select="$totalMinFees"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="checkDenomination">
<xsl:param name="allDenominationsAreEqual"/>
<xsl:param name="denoms"/>
<xsl:choose>
<xsl:when test="$allDenominationsAreEqual">
<xsl:call-template name="getDenomination">
<xsl:with-param name="placeholderElement" select="$denoms/denom"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="displayErrorText">
<xsl:with-param name="string">Cannot print denomination: not all fees in
service_breakdown have an equal denomination (tip: if most services are in
eur but one is in usd, add the usd fee to the description for that service
and use an estimated eur for the hourly rate or fee).</xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="calculatePersonDays">
<xsl:variable name="totalMinDurations"
select="sum($serviceNodeSet/entry[@type = 'service']/dh/min)"/>
<xsl:variable name="totalMaxDurations"
select="sum($serviceNodeSet/entry[@type = 'service']/dh/max)"/>
<xsl:choose>
<xsl:when test="not($totalMinDurations = $totalMaxDurations)">
<xsl:value-of select="sum($totalMinDurations) div 8"/>
<xsl:text> - </xsl:text>
<xsl:value-of select="sum($totalMaxDurations) div 8"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="sum($totalMinDurations) div 8"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="prettyMissingDecimal">
<xsl:param name="n"/>
<xsl:if test="floor($n) = $n">
<xsl:value-of select="$n"/>
<xsl:text>.-</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet> </xsl:stylesheet>

View File

@ -2,15 +2,17 @@
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="http://www.radical.sexy" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="http://www.radical.sexy"
exclude-result-prefixes="xs my" version="2.0"> exclude-result-prefixes="xs my" version="2.0">
<!-- color scheme, just change these to change colors throughout the suite --> <!-- color scheme, just change these to change colors throughout the suite -->
<xsl:variable name="c_main">#e2632a</xsl:variable> <xsl:variable name="c_main">#e2632a</xsl:variable>
<xsl:variable name="c_support_light">#ededed</xsl:variable> <xsl:variable name="c_support_light">#ededed</xsl:variable>
<xsl:variable name="c_support_subtlydarkerlight">#e4e4e4</xsl:variable><!-- used for subtle light border around support_light background --> <xsl:variable name="c_support_subtlydarkerlight">#e4e4e4</xsl:variable>
<xsl:variable name="c_support_medium">#999999</xsl:variable><!-- used for subtle light border around support_light background --> <!-- used for subtle light border around support_light background -->
<xsl:variable name="c_support_medium">#999999</xsl:variable>
<!-- used for subtle light border around support_light background -->
<xsl:variable name="c_support_dark">#444444</xsl:variable> <xsl:variable name="c_support_dark">#444444</xsl:variable>
<xsl:variable name="c_main_contrast">white</xsl:variable> <xsl:variable name="c_main_contrast">white</xsl:variable>
<xsl:variable name="border-color">#444444</xsl:variable> <xsl:variable name="border-color">#444444</xsl:variable>
<!-- auto numbering format (used in various docs) --> <!-- auto numbering format (used in various docs) -->
@ -32,7 +34,7 @@
<xsl:variable name="hourly_fee" select="/contract/meta/contractor/hourly_fee * 1"/> <xsl:variable name="hourly_fee" select="/contract/meta/contractor/hourly_fee * 1"/>
<xsl:variable name="plannedHours" select="/contract/meta/work/planning/hours * 1"/> <xsl:variable name="plannedHours" select="/contract/meta/work/planning/hours * 1"/>
<xsl:variable name="total_fee" select="$hourly_fee * $plannedHours"/> <xsl:variable name="total_fee" select="$hourly_fee * $plannedHours"/>
<!-- current second ('random' seed) --> <!-- current second ('random' seed) -->
<xsl:variable name="current_second" select="ceiling(seconds-from-dateTime(current-dateTime()))"/> <xsl:variable name="current_second" select="ceiling(seconds-from-dateTime(current-dateTime()))"/>
@ -75,7 +77,194 @@
<xsl:variable name="generic_piecolor_20">mediumturquoise</xsl:variable> <xsl:variable name="generic_piecolor_20">mediumturquoise</xsl:variable>
<xsl:variable name="generic_piecolor_21">navy</xsl:variable> <xsl:variable name="generic_piecolor_21">navy</xsl:variable>
<xsl:variable name="generic_piecolor_other">black</xsl:variable> <xsl:variable name="generic_piecolor_other">black</xsl:variable>
<xsl:variable name="serviceNodeSet">
<!-- putting the logic for all calculation in this imaginary nodeset; output to fo comes below -->
<xsl:for-each select="//breakdown/service | //breakdown/extra">
<xsl:variable name="minmaxeffortPresent"
select="boolean(effort/min and effort/max)"/>
<xsl:variable name="minmaxFeePresent" select="boolean(fee/min and fee/max)"/>
<xsl:variable name="effortPresent"
select="boolean(normalize-space(effort) and normalize-space(effort/@in))"/>
<xsl:variable name="optional" select="@optional = 'yes'"/>
<entry>
<xsl:attribute name="denomination">
<xsl:value-of select="fee/@denomination"/>
</xsl:attribute>
<xsl:attribute name="estimate">
<xsl:value-of select="fee/@estimate = 'yes'"/>
</xsl:attribute>
<xsl:attribute name="type">
<xsl:value-of select="local-name(.)"/>
</xsl:attribute>
<xsl:attribute name="optional">
<xsl:value-of select="@optional"/>
</xsl:attribute>
<desc>
<xsl:if test="$optional">
<xsl:text>(Optional) </xsl:text>
</xsl:if>
<xsl:value-of select="description"/>
</desc>
<xsl:if test="$effortPresent">
<d>
<xsl:choose>
<xsl:when test="$minmaxeffortPresent">
<!-- Estimated effort -->
<xsl:value-of select="effort/min"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="effort/max"/>
<xsl:text> </xsl:text>
<xsl:value-of select="effort/@in"/>
</xsl:when>
<xsl:otherwise>
<!-- Actual effort -->
<xsl:value-of select="effort"/>
<xsl:text> </xsl:text>
<xsl:value-of select="effort/@in"/>
</xsl:otherwise>
</xsl:choose>
</d>
<dh>
<!-- effort in hours, for calculation of persondays -->
<xsl:choose>
<xsl:when test="$minmaxeffortPresent">
<!-- computed + estimated fee; compute for min and max using effort and use hourly rate denomination -->
<min>
<xsl:choose>
<xsl:when test="$optional">0</xsl:when>
<xsl:when test="effort/@in = 'hours'">
<xsl:value-of select="effort/min"/>
</xsl:when>
<xsl:when test="effort/@in = 'days'">
<xsl:value-of select="effort/min * 8"/>
</xsl:when>
</xsl:choose>
</min>
<max>
<xsl:choose>
<xsl:when test="effort/@in = 'hours'">
<xsl:value-of select="effort/max"/>
</xsl:when>
<xsl:when test="effort/@in = 'days'">
<xsl:value-of select="effort/max * 8"/>
</xsl:when>
</xsl:choose>
</max>
</xsl:when>
<xsl:otherwise>
<min>
<xsl:choose>
<xsl:when test="$optional">0</xsl:when>
<xsl:when test="effort/@in = 'hours'">
<xsl:value-of select="effort"/>
</xsl:when>
<xsl:when test="effort/@in = 'days'">
<xsl:value-of select="effort * 8"/>
</xsl:when>
</xsl:choose>
</min>
<max>
<xsl:choose>
<xsl:when test="effort/@in = 'hours'">
<xsl:value-of select="effort"/>
</xsl:when>
<xsl:when test="effort/@in = 'days'">
<xsl:value-of select="effort * 8"/>
</xsl:when>
</xsl:choose>
</max>
</xsl:otherwise>
</xsl:choose>
</dh>
<h>
<xsl:value-of select="hourly_rate"/>
</h>
</xsl:if>
<f>
<xsl:choose>
<xsl:when test="fee/computed">
<!-- Fee computed; need effort and rate -->
<xsl:choose>
<xsl:when test="not($effortPresent) or not(hourly_rate)">
<xsl:message terminate="yes">ERROR: cannot compute fee for
<xsl:value-of select="local-name(.)"/> "<xsl:value-of
select="description"/>" - effort and/or hourly rate
missing </xsl:message>
</xsl:when>
<xsl:when test="$effortPresent and $minmaxeffortPresent">
<!-- computed + estimated fee; compute for min and max using effort and use hourly rate denomination -->
<min>
<xsl:choose>
<xsl:when test="$optional">0</xsl:when>
<xsl:otherwise>
<xsl:call-template name="computeFee">
<xsl:with-param name="for" select="effort/min"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</min>
<max>
<xsl:call-template name="computeFee">
<xsl:with-param name="for" select="effort/max"/>
</xsl:call-template>
</max>
</xsl:when>
<xsl:otherwise>
<!-- computed fee; compute using effort and use hourly rate denomination -->
<min>
<xsl:choose>
<xsl:when test="$optional">0</xsl:when>
<xsl:otherwise>
<xsl:call-template name="computeFee">
<xsl:with-param name="for" select="effort"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</min>
<max>
<xsl:call-template name="computeFee">
<xsl:with-param name="for" select="effort"/>
</xsl:call-template>
</max>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<!-- Fee set by user -->
<xsl:choose>
<xsl:when test="$minmaxFeePresent">
<xsl:copy-of select="fee/node()"/>
</xsl:when>
<xsl:otherwise>
<min>
<xsl:copy-of select="fee/text()"/>
</min>
<max>
<xsl:copy-of select="fee/text()"/>
</max>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</f>
</entry>
</xsl:for-each>
</xsl:variable>
<xsl:template name="computeFee">
<xsl:param name="for"/>
<xsl:choose>
<xsl:when test="effort/@in = 'hours'">
<!-- multiply with hourly rate -->
<xsl:value-of select="$for * hourly_rate"/>
</xsl:when>
<xsl:when test="effort/@in = 'days'">
<!-- multiply with hourly rate * 8 -->
<xsl:value-of select="$for * hourly_rate * 8"/>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="selectColor"> <xsl:template name="selectColor">
<xsl:param name="label"/> <xsl:param name="label"/>
<xsl:param name="position"/> <xsl:param name="position"/>
@ -239,57 +428,11 @@
</xsl:otherwise> </xsl:otherwise>
</xsl:choose> </xsl:choose>
</xsl:variable> </xsl:variable>
<!-- Finding stuff --> <!-- Finding stuff -->
<xsl:variable name="unsortedFindingSummaryTable"> <xsl:variable name="unsortedFindingSummaryTable">
<xsl:for-each-group select="//finding" group-by="@threatLevel"> <xsl:for-each-group select="//finding" group-by="@threatLevel">
<xsl:for-each select="current-group()"> <xsl:for-each select="current-group()">
<findingEntry>
<xsl:attribute name="Ref">
<xsl:value-of select="@Ref"/>
</xsl:attribute>
<xsl:attribute name="status">
<xsl:value-of select="@status"/>
</xsl:attribute>
<xsl:attribute name="findingId">
<xsl:value-of select="@id"/>
</xsl:attribute>
<findingNumber>
<xsl:apply-templates select="." mode="number"/>
</findingNumber>
<findingType>
<xsl:value-of select="@type"/>
</findingType>
<findingDescription>
<xsl:choose>
<xsl:when test="description_summary">
<xsl:value-of select="description_summary"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="description" mode="summarytable"/>
</xsl:otherwise>
</xsl:choose>
</findingDescription>
<findingThreatLevel>
<xsl:value-of select="current-grouping-key()"/>
</findingThreatLevel>
</findingEntry>
</xsl:for-each>
</xsl:for-each-group>
</xsl:variable>
<xsl:variable name="findingSummaryTable">
<xsl:for-each select="$unsortedFindingSummaryTable/findingEntry">
<xsl:sort data-type="number" order="descending"
select="
(number(findingThreatLevel = 'Extreme') * 10)
+ (number(findingThreatLevel = 'High') * 9)
+ (number(findingThreatLevel = 'Elevated') * 8)
+ (number(findingThreatLevel = 'Moderate') * 7)
+ (number(findingThreatLevel = 'Low') * 6)
+ (number(findingThreatLevel = 'Unknown') * 3)
+ (number(findingThreatLevel = 'N/A') * 1)"/>
<xsl:variable name="findingThreatLevelClean"
select="translate(findingThreatLevel, '/', '_')"/>
<findingEntry> <findingEntry>
<xsl:attribute name="Ref"> <xsl:attribute name="Ref">
<xsl:value-of select="@Ref"/> <xsl:value-of select="@Ref"/>
@ -298,29 +441,75 @@
<xsl:value-of select="@status"/> <xsl:value-of select="@status"/>
</xsl:attribute> </xsl:attribute>
<xsl:attribute name="findingId"> <xsl:attribute name="findingId">
<xsl:value-of select="@findingId"/> <xsl:value-of select="@id"/>
</xsl:attribute> </xsl:attribute>
<!-- add an id for the first entry of each type so that we can link to it -->
<xsl:if
test="not(preceding-sibling::findingEntry/findingThreatLevel = findingThreatLevel)">
<xsl:attribute name="id">summaryTableThreatLevel<xsl:value-of
select="$findingThreatLevelClean"/></xsl:attribute>
</xsl:if>
<findingNumber> <findingNumber>
<xsl:value-of select="findingNumber"/> <xsl:apply-templates select="." mode="number"/>
</findingNumber> </findingNumber>
<findingType> <findingType>
<xsl:value-of select="findingType"/> <xsl:value-of select="@type"/>
</findingType> </findingType>
<findingDescription> <findingDescription>
<xsl:value-of select="findingDescription"/> <xsl:choose>
<xsl:when test="description_summary">
<xsl:value-of select="description_summary"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="description" mode="summarytable"/>
</xsl:otherwise>
</xsl:choose>
</findingDescription> </findingDescription>
<findingThreatLevel> <findingThreatLevel>
<xsl:value-of select="findingThreatLevel"/> <xsl:value-of select="current-grouping-key()"/>
</findingThreatLevel> </findingThreatLevel>
</findingEntry> </findingEntry>
</xsl:for-each> </xsl:for-each>
</xsl:variable> </xsl:for-each-group>
</xsl:variable>
<xsl:variable name="findingSummaryTable">
<xsl:for-each select="$unsortedFindingSummaryTable/findingEntry">
<xsl:sort data-type="number" order="descending"
select="
(number(findingThreatLevel = 'Extreme') * 10)
+ (number(findingThreatLevel = 'High') * 9)
+ (number(findingThreatLevel = 'Elevated') * 8)
+ (number(findingThreatLevel = 'Moderate') * 7)
+ (number(findingThreatLevel = 'Low') * 6)
+ (number(findingThreatLevel = 'Unknown') * 3)
+ (number(findingThreatLevel = 'N/A') * 1)"/>
<xsl:variable name="findingThreatLevelClean"
select="translate(findingThreatLevel, '/', '_')"/>
<findingEntry>
<xsl:attribute name="Ref">
<xsl:value-of select="@Ref"/>
</xsl:attribute>
<xsl:attribute name="status">
<xsl:value-of select="@status"/>
</xsl:attribute>
<xsl:attribute name="findingId">
<xsl:value-of select="@findingId"/>
</xsl:attribute>
<!-- add an id for the first entry of each type so that we can link to it -->
<xsl:if
test="not(preceding-sibling::findingEntry/findingThreatLevel = findingThreatLevel)">
<xsl:attribute name="id">summaryTableThreatLevel<xsl:value-of
select="$findingThreatLevelClean"/></xsl:attribute>
</xsl:if>
<findingNumber>
<xsl:value-of select="findingNumber"/>
</findingNumber>
<findingType>
<xsl:value-of select="findingType"/>
</findingType>
<findingDescription>
<xsl:value-of select="findingDescription"/>
</findingDescription>
<findingThreatLevel>
<xsl:value-of select="findingThreatLevel"/>
</findingThreatLevel>
</findingEntry>
</xsl:for-each>
</xsl:variable>
<!-- Money stuff --> <!-- Money stuff -->
<xsl:variable name="eur" select="'eur'"/> <xsl:variable name="eur" select="'eur'"/>
@ -402,7 +591,7 @@
</xsl:otherwise> </xsl:otherwise>
</xsl:choose> </xsl:choose>
</xsl:function> </xsl:function>
<xsl:function name="my:calculatePeriod"> <xsl:function name="my:calculatePeriod">
<xsl:param name="enddate"/> <xsl:param name="enddate"/>
<xsl:param name="startdate"/> <xsl:param name="startdate"/>

View File

@ -189,9 +189,17 @@
</xsl:template> </xsl:template>
<xsl:template match="p_persondays"> <xsl:template match="p_persondays">
<xsl:param name="placeholderElement" select="/*/meta/activityinfo/persondays"/> <xsl:param name="placeholderElement" select="/*/meta/activityinfo/persondays"/>
<xsl:call-template name="checkPlaceholder"> <xsl:choose>
<xsl:with-param name="placeholderElement" select="$placeholderElement"/> <xsl:when
</xsl:call-template> test="$placeholderElement = '' or $placeholderElement = '0' or not($placeholderElement)">
<xsl:call-template name="calculatePersonDays"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="checkPlaceholder">
<xsl:with-param name="placeholderElement" select="$placeholderElement"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template> </xsl:template>
<xsl:template match="p_boxtype"> <xsl:template match="p_boxtype">
<xsl:param name="placeholderElement" select="/*/meta/activityinfo/type"/> <xsl:param name="placeholderElement" select="/*/meta/activityinfo/type"/>
@ -201,13 +209,21 @@
</xsl:template> </xsl:template>
<xsl:template match="p_fee"> <xsl:template match="p_fee">
<xsl:param name="placeholderElement" select="/*/meta/activityinfo/fee"/> <xsl:param name="placeholderElement" select="/*/meta/activityinfo/fee"/>
<xsl:call-template name="getDenomination"> <xsl:choose>
<xsl:with-param name="placeholderElement" select="$placeholderElement"/> <xsl:when
</xsl:call-template> test="$placeholderElement = '' or $placeholderElement = '0' or not($placeholderElement)">
<xsl:text>&#160;</xsl:text> <xsl:call-template name="calculateTotal"/>
<xsl:call-template name="checkPlaceholder"> </xsl:when>
<xsl:with-param name="placeholderElement" select="$placeholderElement"/> <xsl:otherwise>
</xsl:call-template> <xsl:call-template name="getDenomination">
<xsl:with-param name="placeholderElement" select="$placeholderElement"/>
</xsl:call-template>
<xsl:text>&#160;</xsl:text>
<xsl:call-template name="checkPlaceholder">
<xsl:with-param name="placeholderElement" select="$placeholderElement"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template> </xsl:template>
<xsl:template match="p_startdate"> <xsl:template match="p_startdate">
<xsl:param name="placeholderElement" select="/*/meta/activityinfo/planning/start"/> <xsl:param name="placeholderElement" select="/*/meta/activityinfo/planning/start"/>
@ -496,17 +512,17 @@
</xsl:when> </xsl:when>
<!-- PRETTY FORMATTING FOR DATES --> <!-- PRETTY FORMATTING FOR DATES -->
<xsl:when <xsl:when
test="(self::contract_end_date or self::contract_start_date or self::generate_raterevisiondate or self::p_startdate or self::p_enddate) and string($placeholderElement) castable as xs:date"> test="(self::contract_end_date or self::contract_start_date or self::generate_raterevisiondate or self::p_startdate or self::p_enddate or self::p_reportdue) and string($placeholderElement) castable as xs:date">
<!-- pretty printing for date --> <!-- pretty printing for date -->
<xsl:value-of <xsl:value-of
select="format-date($placeholderElement, '[MNn] [D1], [Y]', 'en', (), ())" select="format-date($placeholderElement, '[MNn] [D1], [Y]', 'en', (), ())"
/> />
</xsl:when> </xsl:when>
<xsl:when <xsl:when
test="(self::contract_end_date or self::contract_start_date or self::generate_raterevisiondate or self::p_startdate or self::p_enddate) and normalize-space(.) = 'TBD'"> test="(self::contract_end_date or self::contract_start_date or self::generate_raterevisiondate or self::p_startdate or self::p_enddate or self::p_reportdue) and normalize-space(.) = 'TBD'">
<!-- actual TBD, don't mess with it --> TBD </xsl:when> <!-- actual TBD, don't mess with it --> TBD </xsl:when>
<xsl:when <xsl:when
test="(self::contract_end_date or self::contract_start_date or self::generate_raterevisiondate or self::p_startdate or self::p_enddate) and not(string($placeholderElement) castable as xs:date)"> test="(self::contract_end_date or self::contract_start_date or self::generate_raterevisiondate or self::p_startdate or self::p_enddate or self::p_reportdue) and not(string($placeholderElement) castable as xs:date)">
<xsl:call-template name="displayErrorText"> <xsl:call-template name="displayErrorText">
<xsl:with-param name="string">TBD</xsl:with-param> <xsl:with-param name="string">TBD</xsl:with-param>
</xsl:call-template> </xsl:call-template>

View File

@ -442,4 +442,7 @@
<xsl:attribute name="start-indent">0</xsl:attribute> <xsl:attribute name="start-indent">0</xsl:attribute>
<xsl:attribute name="end-indent">0</xsl:attribute> <xsl:attribute name="end-indent">0</xsl:attribute>
</xsl:attribute-set> </xsl:attribute-set>
<xsl:attribute-set name="totalRow"/>
<xsl:attribute-set name="totalcell"/>
</xsl:stylesheet> </xsl:stylesheet>

View File

@ -26,4 +26,13 @@
<xsl:attribute-set name="region-body-cover"> <xsl:attribute-set name="region-body-cover">
</xsl:attribute-set> </xsl:attribute-set>
<!-- service breakdown -->
<xsl:attribute-set name="totalcell">
<xsl:attribute name="text-align-last">justify</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="totalRow">
<xsl:attribute name="border-top">1px solid black</xsl:attribute>
</xsl:attribute-set>
</xsl:stylesheet> </xsl:stylesheet>