]> wagnertech.de Git - kivitendo-erp.git/commitdiff
Pflichtenhefte: Faktor für Verkaufspreis in Abschnitten & »Kostenschätzung« umbenannt
authorMoritz Bunkus <m.bunkus@linet-services.de>
Wed, 7 Sep 2016 11:32:35 +0000 (13:32 +0200)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Mon, 7 Nov 2016 12:19:30 +0000 (13:19 +0100)
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.

SL/Controller/RequirementSpecOrder.pm
SL/DB/MetaSetup/RequirementSpecItem.pm
locale/de/all
sql/Pg-upgrade2/requirement_spec_items_price_factor.sql [new file with mode: 0644]
templates/webpages/requirement_spec/_show_time_and_cost_estimate.html
templates/webpages/requirement_spec/_show_time_and_cost_estimate_item.html
templates/webpages/requirement_spec/show.html
templates/webpages/requirement_spec_item/_section_form.html
templates/webpages/requirement_spec_item/_section_header.html

index f695a510a648f59318d139443ce31fae5b5578b5..a949901f1610768e3e5598f720b116bbff6f0efb 100644 (file)
@@ -318,8 +318,8 @@ sub create_order_item {
     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,
   );
index 07bac0761e67c06f0e85c19ea4e1169ed5eb4ec5..50c167deda61d437c4d8fd7c192ac52f2afafece 100644 (file)
@@ -24,6 +24,7 @@ __PACKAGE__->meta->columns(
   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' },
 );
index 56478f53a2840cba3997af21db066e5da02de927..9347f38de7fb7178b0b57774d26a664cab62d967 100755 (executable)
@@ -624,7 +624,6 @@ $self->{texts} = {
   'Copy requirement spec'       => 'Pflichtenheft kopieren',
   'Copy template'               => 'Vorlage kopieren',
   'Correct taxkey'              => 'Richtiger Steuerschlüssel',
-  'Cost'                        => 'Kosten',
   '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"',
@@ -3185,7 +3184,8 @@ $self->{texts} = {
   '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',
diff --git a/sql/Pg-upgrade2/requirement_spec_items_price_factor.sql b/sql/Pg-upgrade2/requirement_spec_items_price_factor.sql
new file mode 100644 (file)
index 0000000..b519b38
--- /dev/null
@@ -0,0 +1,9 @@
+-- @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;
index e8e4c3d5215a2618432578af58f89f4a0f271e3e..2cff5d9f25b69487587c555ee4a36c424ba185e2 100644 (file)
@@ -1,5 +1,6 @@
 [%- 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 %]
@@ -18,7 +19,7 @@
       <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>
       [%- END %]
      </tr>
 
       [%- 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 %]
-        <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 -%]
@@ -50,7 +54,7 @@
      <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>
index c3d21e3b95c0654e7762942429d7392295ed8462..d051972479e6308fe403b3a346f78a6307cc20a2 100644 (file)
@@ -8,7 +8,7 @@
  [%- 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>&nbsp;</td>
 [%- 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 %]
-   <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 -%]
index 285dcee155c0d37b1c69891047659b80b5294cdd..c627a1685d479daf0a1cd342a8d909cfcfed7380 100644 (file)
@@ -11,7 +11,7 @@
  <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>
index 93d75bed82f13064b0006548be4cbb555f92c48c..14c5af5bebe9cff4cd33f36f9ab4571f09d592fe 100644 (file)
   </p>
  [%- END %]
 
- <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">
index 4df9892e261657a0bf4354bfb957e14b6c8defde..4c4743f625870c8ddd27e39b4d3d1b025bf19991 100644 (file)
@@ -18,3 +18,7 @@
   <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>