Aktuell haben wir nur einen Verkaufsbasispreis im Pflichtenheft: den
Stundensatz in den Grundeinstellungen. Dies ist allerdings der
Stundensatz, der Kunden gegenüber in Rechnung gestellt wird, und damit
ein Verkaufspreis und kein Kostenfaktor. Die Kosten anhand des
Verkaufspreises abzuschätzen ist aber unsinnig.
Daher ist es sinnvoller, erst mal von »Zeit- und Preisschätzung«
anstelle von »Zeit- und Kostenschätzung«.
Der neu eingeführte Faktor, der an Abschnitten angegeben werden kann,
ist dann ein Multiplikator für die Verkaufspreisschätzung. Er kann
z.B. benutzt werden, um geplante Wochenendarbeiten höher zu bepreisen.
Eine Einführung von echter Kostenschätzungen würde etwas mehr Arbeit
erfordern.
longdescription => $longdescription,
qty => $is_time_based ? $section->time_estimation * 1 : 1,
unit => $is_time_based ? $self->h_unit_name : $part->unit,
longdescription => $longdescription,
qty => $is_time_based ? $section->time_estimation * 1 : 1,
unit => $is_time_based ? $self->h_unit_name : $part->unit,
- sellprice => $::form->round_amount($self->requirement_spec->hourly_rate * ($is_time_based ? 1 : $section->time_estimation), 2),
- lastcost => $part->lastcost,
+ sellprice => $::form->round_amount($self->requirement_spec->hourly_rate * ($is_time_based ? 1 : $section->time_estimation * $section->sellprice_factor), 2),
+ lastcost => $part->lastcost * $section->sellprice_factor,
discount => 0,
project_id => $self->requirement_spec->project_id,
);
discount => 0,
project_id => $self->requirement_spec->project_id,
);
position => { type => 'integer', not_null => 1 },
requirement_spec_id => { type => 'integer', not_null => 1 },
risk_id => { type => 'integer' },
position => { type => 'integer', not_null => 1 },
requirement_spec_id => { type => 'integer', not_null => 1 },
risk_id => { type => 'integer' },
+ sellprice_factor => { type => 'numeric', default => 1, precision => 10, scale => 5 },
time_estimation => { type => 'numeric', default => '0', not_null => 1, precision => 12, scale => 2 },
title => { type => 'text' },
);
time_estimation => { type => 'numeric', default => '0', not_null => 1, precision => 12, scale => 2 },
title => { type => 'text' },
);
'Copy requirement spec' => 'Pflichtenheft kopieren',
'Copy template' => 'Vorlage kopieren',
'Correct taxkey' => 'Richtiger Steuerschlüssel',
'Copy requirement spec' => 'Pflichtenheft kopieren',
'Copy template' => 'Vorlage kopieren',
'Correct taxkey' => 'Richtiger Steuerschlüssel',
'Costs' => 'Kosten',
'Could not load class #1 (#2): "#3"' => 'Konnte Klasse #1 (#2) nicht laden: "#3"',
'Could not load class #1, #2' => 'Konnte Klasse #1 nicht laden: "#2"',
'Costs' => 'Kosten',
'Could not load class #1 (#2): "#3"' => 'Konnte Klasse #1 (#2) nicht laden: "#3"',
'Could not load class #1, #2' => 'Konnte Klasse #1 nicht laden: "#2"',
'This will set an exact price.' => 'Diese Option setzt einen festen Preis.',
'Three Options:' => 'Drei Optionen:',
'Time Format' => 'Uhrzeitformat',
'This will set an exact price.' => 'Diese Option setzt einen festen Preis.',
'Three Options:' => 'Drei Optionen:',
'Time Format' => 'Uhrzeitformat',
- 'Time and cost estimate' => 'Zeit- und Kostenschätzung',
+ 'Time Tracking' => 'Zeiterfassung',
+ 'Time and price estimate' => 'Zeit- und Preisschätzung',
'Time estimate' => 'Zeitschätzung',
'Time period for the analysis:' => 'Analysezeitraum:',
'Time/cost estimate actions' => 'Aktionen für Kosten-/Zeitabschätzung',
'Time estimate' => 'Zeitschätzung',
'Time period for the analysis:' => 'Analysezeitraum:',
'Time/cost estimate actions' => 'Aktionen für Kosten-/Zeitabschätzung',
--- /dev/null
+-- @tag: requirement_spec_items_price_factor
+-- @description: Pflichtenheftabschnitte: Faktor für Verkaufspreis
+-- @depends: requirement_specs
+ALTER TABLE requirement_spec_items
+ ADD COLUMN sellprice_factor NUMERIC(10, 5),
+ ALTER COLUMN sellprice_factor SET DEFAULT 1;
+
+UPDATE requirement_spec_items
+SET sellprice_factor = 1;
[%- USE LxERP -%][%- USE L -%][%- USE HTML -%][%- USE P -%]
[%- DEFAULT id_prefix = 'time_and_cost_estimate_form' %]
[%- USE LxERP -%][%- USE L -%][%- USE HTML -%][%- USE P -%]
[%- DEFAULT id_prefix = 'time_and_cost_estimate_form' %]
+[%- SET total_cost = 0 %]
<div id="time_cost_estimate"[% IF initially_hidden %] style="display: none;"[% END %]>
[%- IF !SELF.requirement_spec.sections.size %]
<div id="time_cost_estimate"[% IF initially_hidden %] style="display: none;"[% END %]>
[%- IF !SELF.requirement_spec.sections.size %]
<th>[%- LxERP.t8("Risk") %]</th>
<th align="right">[%- LxERP.t8("Time estimate") %]</th>
[%- UNLESS SELF.requirement_spec.is_template %]
<th>[%- LxERP.t8("Risk") %]</th>
<th align="right">[%- LxERP.t8("Time estimate") %]</th>
[%- UNLESS SELF.requirement_spec.is_template %]
- <th align="right">[%- LxERP.t8("Cost") %]</th>
+ <th align="right">[%- LxERP.t8("Price") %]</th>
[%- SET at_least_one_function_block = 1 %]
[%- FOREACH child = section.children_sorted %]
[%- INCLUDE 'requirement_spec/_show_time_and_cost_estimate_item.html'
[%- SET at_least_one_function_block = 1 %]
[%- FOREACH child = section.children_sorted %]
[%- INCLUDE 'requirement_spec/_show_time_and_cost_estimate_item.html'
- item = child
- level = 1 %]
+ section = section
+ item = child
+ level = 1 %]
[%- END %]
<tr class="listrow subtotal">
<td style="padding-left: 50px" colspan="3" class="sum">[%- LxERP.t8("Sum for section") -%]:</td>
<td align="right" nowrap>[%- P.format_man_days(section.time_estimation, 'skip_zero'=1) -%]</td>
[%- UNLESS SELF.requirement_spec.is_template %]
[%- END %]
<tr class="listrow subtotal">
<td style="padding-left: 50px" colspan="3" class="sum">[%- LxERP.t8("Sum for section") -%]:</td>
<td align="right" nowrap>[%- P.format_man_days(section.time_estimation, 'skip_zero'=1) -%]</td>
[%- UNLESS SELF.requirement_spec.is_template %]
- <td align="right" nowrap>[%- LxERP.format_amount(section.time_estimation * SELF.requirement_spec.hourly_rate, 2) -%] EUR</td>
+ [%- SET section_cost = section.time_estimation * SELF.requirement_spec.hourly_rate * section.sellprice_factor;
+ total_cost = total_cost + section_cost %]
+ <td align="right" nowrap>[%- LxERP.format_amount(section_cost, 2) -%] EUR</td>
[%- END %]
</tr>
[%- END -%]
[%- END %]
</tr>
[%- END -%]
<td colspan="3">[%- LxERP.t8("Sum for #1", SELF.requirement_spec.type.description) -%]:</td>
<td align="right" nowrap>[%- P.format_man_days(SELF.requirement_spec.time_estimation) -%]</td>
[%- UNLESS SELF.requirement_spec.is_template %]
<td colspan="3">[%- LxERP.t8("Sum for #1", SELF.requirement_spec.type.description) -%]:</td>
<td align="right" nowrap>[%- P.format_man_days(SELF.requirement_spec.time_estimation) -%]</td>
[%- UNLESS SELF.requirement_spec.is_template %]
- <td align="right" nowrap>[%- LxERP.format_amount(SELF.requirement_spec.time_estimation * SELF.requirement_spec.hourly_rate, 2) -%] EUR</td>
+ <td align="right" nowrap>[%- LxERP.format_amount(total_cost, 2) -%] EUR</td>
[%- END %]
</tr>
</tfoot>
[%- END %]
</tr>
</tfoot>
[%- IF !item.children.size -%]
<td align="right" nowrap>[%- P.format_man_days(item.time_estimation, skip_zero=1) -%]</td>
[%- UNLESS SELF.requirement_spec.is_template %]
[%- IF !item.children.size -%]
<td align="right" nowrap>[%- P.format_man_days(item.time_estimation, skip_zero=1) -%]</td>
[%- UNLESS SELF.requirement_spec.is_template %]
- <td align="right" nowrap>[%- LxERP.format_amount(item.time_estimation * SELF.requirement_spec.hourly_rate, 2) -%] EUR</td>
+ <td align="right" nowrap>[%- LxERP.format_amount(item.time_estimation * SELF.requirement_spec.hourly_rate * section.sellprice_factor, 2) -%] EUR</td>
[%- END %]
[%- ELSE -%]
<td> </td>
[%- END %]
[%- ELSE -%]
<td> </td>
[%- IF item.children.size -%]
[%- FOREACH child = item.children_sorted -%]
[%- INCLUDE 'requirement_spec/_show_time_and_cost_estimate_item.html'
[%- IF item.children.size -%]
[%- FOREACH child = item.children_sorted -%]
[%- INCLUDE 'requirement_spec/_show_time_and_cost_estimate_item.html'
- item = child
- level = level + 1 -%]
+ section = section
+ item = child
+ level = level + 1 -%]
[%- END -%]
<tr class="listrow subtotal">
<td style="padding-left: [%- (level + 1) * 50 -%]px" colspan="3">[%- LxERP.t8("Sum for #1", item.fb_number) -%]:</td>
<td align="right" nowrap>[%- P.format_man_days(item.time_estimation, skip_zero=1) -%]</td>
[%- UNLESS SELF.requirement_spec.is_template %]
[%- END -%]
<tr class="listrow subtotal">
<td style="padding-left: [%- (level + 1) * 50 -%]px" colspan="3">[%- LxERP.t8("Sum for #1", item.fb_number) -%]:</td>
<td align="right" nowrap>[%- P.format_man_days(item.time_estimation, skip_zero=1) -%]</td>
[%- UNLESS SELF.requirement_spec.is_template %]
- <td align="right" nowrap>[%- LxERP.format_amount(item.time_estimation * SELF.requirement_spec.hourly_rate, 2) -%] EUR</td>
+ <td align="right" nowrap>[%- LxERP.format_amount(item.time_estimation * SELF.requirement_spec.hourly_rate * section.sellprice_factor, 2) -%] EUR</td>
[%- END %]
</tr>
[%- END -%]
[%- END %]
</tr>
[%- END -%]
<ul>
<li id="tab-header-function-block"><a href="#function-blocks-tab">[%- LxERP.t8("Content") %]</a></li>
<li id="tab-header-basic-settings"><a href="controller.pl?action=RequirementSpec/ajax_show_basic_settings&id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Basic settings") %]</a></li>
<ul>
<li id="tab-header-function-block"><a href="#function-blocks-tab">[%- LxERP.t8("Content") %]</a></li>
<li id="tab-header-basic-settings"><a href="controller.pl?action=RequirementSpec/ajax_show_basic_settings&id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Basic settings") %]</a></li>
- <li id="tab-header-time-cost-estimate"><a href="controller.pl?action=RequirementSpec/ajax_show_time_and_cost_estimate&id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Time and cost estimate") %]</a></li>
+ <li id="tab-header-time-cost-estimate"><a href="controller.pl?action=RequirementSpec/ajax_show_time_and_cost_estimate&id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Time and price estimate") %]</a></li>
<li id="tab-header-additional-parts"><a href="controller.pl?action=RequirementSpecPart/show&requirement_spec_id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Additional articles") %]</a></li>
[%- UNLESS SELF.requirement_spec.is_template %]
<li id="tab-header-versions"><a href="controller.pl?action=RequirementSpecVersion/list&requirement_spec_id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Versions") %]</a></li>
<li id="tab-header-additional-parts"><a href="controller.pl?action=RequirementSpecPart/show&requirement_spec_id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Additional articles") %]</a></li>
[%- UNLESS SELF.requirement_spec.is_template %]
<li id="tab-header-versions"><a href="controller.pl?action=RequirementSpecVersion/list&requirement_spec_id=[% HTML.url(SELF.requirement_spec.id) %]">[%- LxERP.t8("Versions") %]</a></li>
- <p>
- [%- LxERP.t8("Description") %]:<br>
- [% L.textarea_tag(id_base _ '.description_as_restricted_html', SELF.item.description_as_restricted_html, id=id_base _ '_description', rows=8, cols=80, style=style, class='texteditor') %]
- </p>
-
- <p>
- [% L.ajax_submit_tag('controller.pl?action=RequirementSpecItem/ajax_' _ (SELF.item.id ? 'update' : 'create'), '#' _ id_base _ '_form', LxERP.t8('Save')) %]
- <a href="#" onclick="kivi.requirement_spec.cancel_edit_item_form('[% id_base %]', { to_show: '[% hidden %]' })">[%- LxERP.t8("Cancel") %]</a>
- </p>
+ <table border="0">
+ <tr valign="top">
+ <td>
+ [%- LxERP.t8("Description") %]:<br>
+ [% L.textarea_tag(id_base _ '.description_as_restricted_html', SELF.item.description_as_restricted_html, id=id_base _ '_description', rows=8, cols=80, style=style, class='texteditor') %]<br>
+ [% L.ajax_submit_tag('controller.pl?action=RequirementSpecItem/ajax_' _ (SELF.item.id ? 'update' : 'create'), '#' _ id_base _ '_form', LxERP.t8('Save')) %]
+ <a href="#" onclick="kivi.requirement_spec.cancel_edit_item_form('[% id_base %]', { to_show: '[% hidden %]' })">[%- LxERP.t8("Cancel") %]</a>
+ </td>
+
+ <td>
+ [% LxERP.t8("Price Factor") %]:<br>
+ [% L.input_tag(id_base _ ".sellprice_factor_as_number", SELF.item.sellprice_factor_as_number, size="6") %]<br>
+ </td>
+ </tr>
+ </table>
[%- IF SELF.predefined_texts.size %]
<script type="text/javascript">
[%- IF SELF.predefined_texts.size %]
<script type="text/javascript">
<span class="dimmed-text">[%- LxERP.t8("No text has been entered yet.") %]</span>
[%- END %]
</div>
<span class="dimmed-text">[%- LxERP.t8("No text has been entered yet.") %]</span>
[%- END %]
</div>
+
+<div class="smaller gray" style="text-align:right">
+ [%- LxERP.t8("Price Factor") -%]: [%- LxERP.format_amount(requirement_spec_item.sellprice_factor, -2) -%]
+</div>