From 79398e65cd6534ca6ccd22f8ff7c67617e6ccc53 Mon Sep 17 00:00:00 2001 From: "G. Richardson" Date: Wed, 14 Apr 2010 10:24:45 +0200 Subject: [PATCH] Neuer Bericht "Verkaufsbericht" unter Verkauf->Berichte MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Vor allem interessant für Wiederverkäufer, die ihre Margen anzeigen wollen und EK-Preis pflegen. Neue Dateien bin/mozilla/vk.pl und SL/VK.pm, sowie template unter templates/webpages/vk * Auflistung aller verkauften Artikel mit VK-Preis, EK-Preis und Margen * Sortiert nach Kunden und Artikeln oder Artikeln und Kunden * Preisfaktor (Preis pro 100) bei Gesamtbetrag berücksichtigt * Anzahl der Dezimalstellen einstellbar (für bestimmte Spalten) * Einheit als Anzeigeoption (aber keine Umrechnung, z.B. kg->g) Stornos und stornierte Rechnung aus VK-Bericht herausgefiltert 1) für Auswertungen gar nicht nötig 2) bei Storno wird in invoice marge_total und marge_percent nicht gesetzt deshalb dynamisch für VK-Bericht berechnet, auch wenn es jetzt nicht mehr angezeigt wird Macht es überhaupt Sinn bei Stornos dann invoice mit Margenwerten zu befüllen? Nicht berücksichtigt: * Einkauf Noch Fehlerhaft: * Abwechselndes grau/beige in Ansicht unregelmäßig, generelle Formatierung der Ausgabe (z.T. noch farbig) --- SL/VK.pm | 114 +++++++ bin/mozilla/vk.pl | 392 ++++++++++++++++++++++ css/lx-office-erp.css | 8 + doc/changelog | 1 + locale/de/all | 16 + menu.ini | 6 + templates/webpages/vk/search_invoice.html | 173 ++++++++++ vk.pl | 1 + 8 files changed, 711 insertions(+) create mode 100644 SL/VK.pm create mode 100644 bin/mozilla/vk.pl create mode 100644 templates/webpages/vk/search_invoice.html create mode 120000 vk.pl diff --git a/SL/VK.pm b/SL/VK.pm new file mode 100644 index 000000000..458c35158 --- /dev/null +++ b/SL/VK.pm @@ -0,0 +1,114 @@ +#===================================================================== +# LX-Office ERP +# Copyright (C) 2004 +# Based on SQL-Ledger Version 2.1.9 +# Web http://www.lx-office.org +# +#===================================================================== +# SQL-Ledger Accounting +# Copyright (C) 2001 +# +# Author: Dieter Simader +# Email: dsimader@sql-ledger.org +# Web: http://www.sql-ledger.org +# +# Contributors: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +#====================================================================== +# +# Sold Items report +# +#====================================================================== + +package VK; + +use SL::DBUtils; +use SL::IO; +use SL::MoreCommon; + +use strict; + +sub invoice_transactions { + $main::lxdebug->enter_sub(); + + my ($self, $myconfig, $form) = @_; + + # connect to database + my $dbh = $form->get_standard_dbh($myconfig); + + my @values; + + my $query = + qq|SELECT cus.name,ar.invnumber,ar.id,ar.transdate,p.partnumber,i.parts_id,i.qty,i.price_factor,i.discount,i.description,i.lastcost,i.sellprice,i.marge_total,i.marge_percent,i.unit | . + qq|FROM invoice i | . + qq|join ar on (i.trans_id = ar.id) | . + qq|join parts p on (i.parts_id = p.id) | . + qq|join customer cus on (cus.id = ar.customer_id) |; + + my $where = "1 = 1"; + + # Stornierte Rechnungen und Stornorechnungen in invoice rausfiltern + $where .= " AND ar.storno is not true "; + + my $sortorder = "cus.name,i.parts_id,ar.transdate"; + if ($form->{sortby} eq 'artikelsort') { + $sortorder = "i.parts_id,cus.name,ar.transdate"; + }; + + if ($form->{customer_id}) { + $where .= " AND ar.customer_id = ?"; + push(@values, $form->{customer_id}); + }; + if ($form->{partnumber}) { + $where .= qq| AND (p.partnumber ILIKE ?)|; + push(@values, '%' . $form->{partnumber} . '%'); + } + # nimmt man description am Besten aus invoice oder parts? + if ($form->{description}) { + $where .= qq| AND (i.description ILIKE ?)|; + push(@values, '%' . $form->{description} . '%'); + } + if ($form->{transdatefrom}) { + $where .= " AND ar.transdate >= ?"; + push(@values, $form->{transdatefrom}); + } + if ($form->{transdateto}) { + $where .= " AND ar.transdate <= ?"; + push(@values, $form->{transdateto}); + } + if ($form->{department}) { + my ($null, $department_id) = split /--/, $form->{department}; + $where .= " AND ar.department_id = ?"; + push(@values, $department_id); + } + if ($form->{project_id}) { + $where .= + qq|AND ((ar.globalproject_id = ?) OR EXISTS | . + qq| (SELECT * FROM invoice i | . + qq| WHERE i.project_id = ? AND i.trans_id = ar.id))|; + push(@values, $form->{"project_id"}, $form->{"project_id"}); + } + + $query .= " WHERE $where ORDER BY $sortorder"; + + my @result = selectall_hashref_query($form, $dbh, $query, @values); + + $form->{AR} = [ @result ]; + + $main::lxdebug->leave_sub(); +} + +1; + diff --git a/bin/mozilla/vk.pl b/bin/mozilla/vk.pl new file mode 100644 index 000000000..dbbc2bdc5 --- /dev/null +++ b/bin/mozilla/vk.pl @@ -0,0 +1,392 @@ +#===================================================================== +# LX-Office ERP +# Copyright (C) 2004 +# Based on SQL-Ledger Version 2.1.9 +# Web http://www.lx-office.org +# +#===================================================================== +# SQL-Ledger Accounting +# Copyright (c) 2001 +# +# Author: Dieter Simader +# Email: dsimader@sql-ledger.org +# Web: http://www.sql-ledger.org +# +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +#====================================================================== +# +# Sales report +# +#====================================================================== + +use POSIX qw(strftime); +use List::Util qw(sum first); + +use SL::VK; +use SL::ReportGenerator; +use Data::Dumper; + +require "bin/mozilla/arap.pl"; +require "bin/mozilla/common.pl"; +require "bin/mozilla/drafts.pl"; +require "bin/mozilla/reportgenerator.pl"; + +use strict; + + +sub search_invoice { + $main::lxdebug->enter_sub(); + $main::auth->assert('general_ledger | invoice_edit'); + + my $form = $main::form; + my %myconfig = %main::myconfig; + my $locale = $main::locale; + my $cgi = $main::cgi; + + my ($customer, $department); + + # setup customer selection + $form->all_vc(\%myconfig, "customer", "AR"); + + $form->{title} = $locale->text('Sales Report'); + $form->{jsscript} = 1; + + $form->get_lists("projects" => { "key" => "ALL_PROJECTS", "all" => 1 }, + "departments" => "ALL_DEPARTMENTS", + "customers" => "ALL_VC"); + + $form->{vc_keys} = sub { "$_[0]->{name}--$_[0]->{id}" }; + + $form->header; + print $form->parse_html_template('vk/search_invoice', { %myconfig }); + + $main::lxdebug->leave_sub(); +} + +sub invoice_transactions { + $main::lxdebug->enter_sub(); + + $main::auth->assert('general_ledger | invoice_edit'); + + my $form = $main::form; + my %myconfig = %main::myconfig; + my $locale = $main::locale; + + my ($callback, $href, @columns); + + $form->{customer} = $form->unescape($form->{customer}); + + ($form->{customername}, $form->{customer_id}) = split(/--/, $form->{customer}); + + # decimalplaces überprüfen oder auf Default 2 setzen + $form->{decimalplaces} = 2 unless $form->{decimalplaces} > 0 && $form->{decimalplaces} < 6; + +# report_generator_set_default_sort('transdate', 1); + + VK->invoice_transactions(\%myconfig, \%$form); + + # anhand von radio button die Sortierreihenfolge festlegen + if ($form->{sortby} eq 'artikelsort') { + $form->{'mainsort'} = 'parts_id'; + $form->{'subsort'} = 'name'; + } else { + $form->{'mainsort'} = 'name'; + $form->{'subsort'} = 'parts_id'; + }; + + $form->{title} = $locale->text('Sales Report'); + + @columns = + qw(description invnumber partnumber parts_id transdate qty unit sellprice sellprice_total discount lastcost lastcost_total marge_total marge_percent); + + # hidden variables für pdf/csv export übergeben + # einmal mit l_ um zu bestimmen welche Spalten ausgegeben werden sollen + # einmal optionen für die Überschrift (z.B. transdatefrom, partnumber, ...) + my @hidden_variables = (qw(l_headers l_subtotal l_total transdatefrom transdateto decimalplaces customer customername customer_id department partnumber description project_id), "$form->{db}number", map { "l_$_" } @columns); + my @hidden_nondefault = grep({ $form->{$_} } @hidden_variables); + # Variablen werden dann als Hidden Variable mitgegeben, z.B. + # + + $href = build_std_url('action=invoice_transactions', grep { $form->{$_} } @hidden_variables); + # href = vk.pl?action=invoice_transactions&l_headers=Y&l_subtotal=Y&l_total=Y&transdatefrom=04.03.2010 ... + + my %column_defs = ( + 'description' => { 'text' => $locale->text('Description'), }, + 'partnumber' => { 'text' => $locale->text('Part Number'), }, + 'invnumber' => { 'text' => $locale->text('Invoice Number'), }, + 'transdate' => { 'text' => $locale->text('Invoice Date'), }, + 'qty' => { 'text' => $locale->text('Quantity'), }, + 'unit' => { 'text' => $locale->text('Unit'), }, + 'sellprice' => { 'text' => $locale->text('Sales price'), }, + 'sellprice_total' => { 'text' => $locale->text('Sales net amount'), }, + 'lastcost_total' => { 'text' => $locale->text('Purchase net amount'), }, + 'discount' => { 'text' => $locale->text('Discount'), }, + 'lastcost' => { 'text' => $locale->text('Purchase price'), }, + 'marge_total' => { 'text' => $locale->text('Sales margin'), }, + 'marge_percent' => { 'text' => $locale->text('Sales margin %'), }, + ); + + my %column_alignment = map { $_ => 'right' } qw(lastcost sellprice sellprice_total lastcost_total unit discount marge_total marge_percent qty); + + $form->{"l_type"} = "Y"; + map { $column_defs{$_}->{visible} = $form->{"l_${_}"} ? 1 : 0 } @columns; + + + my @options; + if ($form->{description}) { + push @options, $locale->text('description') . " : $form->{description}"; + } + if ($form->{customer}) { + push @options, $locale->text('Customer') . " : $form->{customername}"; + } + if ($form->{department}) { + my ($department) = split /--/, $form->{department}; + push @options, $locale->text('Department') . " : $department"; + } + if ($form->{invnumber}) { + push @options, $locale->text('Invoice Number') . " : $form->{invnumber}"; + } + if ($form->{invdate}) { + push @options, $locale->text('Invoice Date') . " : $form->{invdate}"; + } + if ($form->{partnumber}) { + push @options, $locale->text('Part Number') . " : $form->{partnumber}"; + } + if ($form->{ordnumber}) { + push @options, $locale->text('Order Number') . " : $form->{ordnumber}"; + } + if ($form->{notes}) { + push @options, $locale->text('Notes') . " : $form->{notes}"; + } + if ($form->{transaction_description}) { + push @options, $locale->text('Transaction description') . " : $form->{transaction_description}"; + } + if ($form->{transdatefrom}) { + push @options, $locale->text('From') . " " . $locale->date(\%myconfig, $form->{transdatefrom}, 1); + } + if ($form->{transdateto}) { + push @options, $locale->text('Bis') . " " . $locale->date(\%myconfig, $form->{transdateto}, 1); + } + + my $report = SL::ReportGenerator->new(\%myconfig, $form); + + $report->set_options('top_info_text' => join("\n", @options), + 'output_format' => 'HTML', + 'title' => $form->{title}, + 'attachment_basename' => $locale->text('sales_report') . strftime('_%Y%m%d', localtime time), + ); + $report->set_options_from_form(); + + $report->set_columns(%column_defs); + $report->set_column_order(@columns); + + $report->set_export_options('invoice_transactions', @hidden_variables, qw(mainsort sortdir)); + + $report->set_sort_indicator($form->{mainsort}, $form->{sortdir}); + + # add sort and escape callback, this one we use for the add sub + $form->{callback} = $href .= "&sort=$form->{mainsort}"; + + # escape callback for href + $callback = $form->escape($href); + + my @subtotal_columns = qw(qty sellprice sellprice_total lastcost lastcost_total marge_total marge_percent discount); + # Gesamtsumme: + # Summe von sellprice_total, lastcost_total und marge_total + # Durchschnitt von marge_percent + my @total_columns = qw(sellprice_total lastcost_total marge_total marge_percent ); + + my %totals = map { $_ => 0 } @total_columns; + my %subtotals1 = map { $_ => 0 } @subtotal_columns; + my %subtotals2 = map { $_ => 0 } @subtotal_columns; + + my $idx = 0; + + foreach my $ar (@{ $form->{AR} }) { + + $ar->{price_factor} = 1 unless $ar->{price_factor}; + # calculate individual sellprice + # discount was already accounted for in db sellprice + $ar->{sellprice} = $ar->{sellprice} / $ar->{price_factor}; + $ar->{lastcost} = $ar->{lastcost} / $ar->{price_factor}; + $ar->{sellprice_total} = $ar->{qty} * $ar->{sellprice}; + $ar->{lastcost_total} = $ar->{qty} * $ar->{lastcost}; + # marge_percent wird neu berechnet, da Wert in invoice leer ist (Bug) + $ar->{marge_percent} = $ar->{sellprice_total} ? (($ar->{sellprice_total}-$ar->{lastcost_total}) / $ar->{sellprice_total}) : 0; + # marge_total neu berechnen + $ar->{marge_total} = $ar->{sellprice_total} ? $ar->{sellprice_total}-$ar->{lastcost_total} : 0; + $ar->{discount} *= 100; # für Ausgabe formatieren, 10% stored as 0.1 in db + + # Anfangshauptüberschrift + if ( $form->{l_headers} eq "Y" && ( $idx == 0 or $ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx - 1]->{ $form->{'mainsort'} } )) { + my $name; + my $headerrow; + if ( $form->{mainsort} eq 'parts_id' ) { + $headerrow->{description}->{data} = "$ar->{description}"; + } else { + $headerrow->{description}->{data} = "$ar->{name}"; + }; + $headerrow->{description}->{class} = "listmainsortheader"; + my $headerrow_set = [ $headerrow ]; + $report->add_data($headerrow_set); + + # add empty row after main header +# my $emptyheaderrow->{description}->{data} = ""; +# $emptyheaderrow->{description}->{class} = "listmainsortheader"; +# my $emptyheaderrow_set = [ $emptyheaderrow ]; +# $report->add_data($emptyheaderrow_set) if $form->{l_headers} eq "Y"; + }; + + # subsort überschriften + if ( $idx == 0 + or $ar->{ $form->{'subsort'} } ne $form->{AR}->[$idx - 1]->{ $form->{'subsort'} } + or $ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx - 1]->{ $form->{'mainsort'} } + ) { + my $headerrow; + my $name; + if ( $form->{subsort} eq 'parts_id' ) { + $name = 'description'; + $headerrow->{description}->{data} = "$ar->{$name}"; + } else { + $name = 'name'; + $headerrow->{description}->{data} = "$ar->{$name}"; + }; + $headerrow->{description}->{class} = "listsubsortheader"; + my $headerrow_set = [ $headerrow ]; + $report->add_data($headerrow_set) if $form->{l_headers} eq "Y"; + }; + + map { $subtotals1{$_} += $ar->{$_}; + $subtotals2{$_} += $ar->{$_}; + } @subtotal_columns; + + map { $totals{$_} += $ar->{$_} } @total_columns; + + $subtotals2{sellprice} = $subtotals2{sellprice_total} / $subtotals2{qty} if $subtotals2{qty} != 0; + $subtotals1{sellprice} = $subtotals1{sellprice_total} / $subtotals1{qty} if $subtotals1{qty} != 0; + $subtotals2{lastcost} = $subtotals2{lastcost_total} / $subtotals2{qty} if $subtotals2{qty} != 0; + $subtotals1{lastcost} = $subtotals1{lastcost_total} / $subtotals1{qty} if $subtotals1{qty} != 0; + + # Ertrag prozentual in den Summen: (summe VK - summe Ertrag) / summe VK + $subtotals1{marge_percent} = $subtotals1{sellprice_total} ? (($subtotals1{sellprice_total} - $subtotals1{lastcost_total}) / $subtotals1{sellprice_total}) : 0; + $subtotals2{marge_percent} = $subtotals2{sellprice_total} ? (($subtotals2{sellprice_total} - $subtotals2{lastcost_total}) / $subtotals2{sellprice_total}) : 0; + + # Ertrag prozentual: (Summe VK betrag - Summe EK betrag) / Summe VK betrag + # wird laufend bei jeder Position neu berechnet + $totals{marge_percent} = $totals{sellprice_total} ? ( ($totals{sellprice_total} - $totals{lastcost_total}) / $totals{sellprice_total} ) : 0; + + map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, 2) } qw(marge_total marge_percent); + map { $ar->{$_} = $form->format_amount(\%myconfig, $ar->{$_}, $form->{"decimalplaces"} )} qw(lastcost sellprice sellprice_total lastcost_total); + + my $row = { }; + + foreach my $column (@columns) { + $row->{$column} = { + 'data' => $ar->{$column}, + 'align' => $column_alignment{$column}, + }; + } + + $row->{description}->{class} = 'listsortdescription'; + + $row->{invnumber}->{link} = build_std_url("script=is.pl", 'action=edit') + . "&id=" . E($ar->{id}) . "&callback=${callback}"; + + my $row_set = [ $row ]; + + if (($form->{l_subtotal} eq 'Y') + && (($idx == (scalar @{ $form->{AR} } - 1)) # last element always has a subtotal + || ($ar->{ $form->{'subsort'} } ne $form->{AR}->[$idx + 1]->{ $form->{'subsort'} }) + || ($ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx + 1]->{ $form->{'mainsort'} }) + )) { # if value that is sorted by changes, print subtotal + my $name; + if ( $form->{subsort} eq 'parts_id' ) { + $name = 'description'; + } else { + $name = 'name'; + }; + + if ($form->{l_subtotal} eq 'Y' ) { + push @{ $row_set }, create_subtotal_row_invoice(\%subtotals2, \@columns, \%column_alignment, \@subtotal_columns, 'listsubsortsubtotal', $ar->{$name}) ; + push @{ $row_set }, insert_empty_row(); + }; + } + + # if mainsort has changed, add mainsort subtotal and empty row + if (($form->{l_subtotal} eq 'Y') + && (($idx == (scalar @{ $form->{AR} } - 1)) # last element always has a subtotal + || ($ar->{ $form->{'mainsort'} } ne $form->{AR}->[$idx + 1]->{ $form->{'mainsort'} }) + )) { # if value that is sorted by changes, print subtotal + my $name; + if ( $form->{mainsort} eq 'parts_id' ) { + $name = 'description'; + } else { + $name = 'name'; + }; + if ($form->{l_subtotal} eq 'Y' ) { + push @{ $row_set }, create_subtotal_row_invoice(\%subtotals1, \@columns, \%column_alignment, \@subtotal_columns, 'listmainsortsubtotal', $ar->{$name}); + push @{ $row_set }, insert_empty_row(); + }; + } + + $report->add_data($row_set); + + $idx++; + } + if ( $form->{l_total} eq "Y" ) { + $report->add_separator(); + $report->add_data(create_subtotal_row_invoice(\%totals, \@columns, \%column_alignment, \@total_columns, 'listtotal')) + }; + + $report->generate_with_headers(); + $main::lxdebug->leave_sub(); +} + + +sub insert_empty_row { + my $dummyrow; + $dummyrow->{description}->{data} = ""; + my $dummyrowset = [ $dummyrow ]; + return $dummyrow; +}; + + + +sub create_subtotal_row_invoice { + $main::lxdebug->enter_sub(); + + my ($totals, $columns, $column_alignment, $subtotal_columns, $class, $name) = @_; + + my $form = $main::form; + my %myconfig = %main::myconfig; + + my $row = { map { $_ => { 'data' => '', 'class' => $class, 'align' => $column_alignment->{$_}, } } @{ $columns } }; + + $row->{description}->{data} = "Summe " . $name; + + map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 2) } qw(marge_total marge_percent); + map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, 0) } qw(qty); + map { $row->{$_}->{data} = $form->format_amount(\%myconfig, $totals->{$_}, $form->{decimalplaces}) } qw(lastcost sellprice sellprice_total lastcost_total); + + + map { $totals->{$_} = 0 } @{ $subtotal_columns }; + + $main::lxdebug->leave_sub(); + + return $row; +} + +1; + diff --git a/css/lx-office-erp.css b/css/lx-office-erp.css index 404c76725..8d09f8e96 100644 --- a/css/lx-office-erp.css +++ b/css/lx-office-erp.css @@ -211,6 +211,14 @@ body.menu { .listtotal, .listtotal td { font-size: 8pt; background-color: rgb(236,233,216); color: black; font-weight: bolder;} +/* Verkaufsbericht */ +.listmainsortheader { font-size: 8pt; background-color: rgb(236,233,216); color: red; font-weight: bolder; padding-left: 10px; padding-top: 0px;} +.listmainsortsubtotal { font-size: 8pt; background-color: rgb(236,233,216); color: red; font-weight: bolder; padding-left: 10px;} +.listsubsortheader { font-size: 8pt; background-color: rgb(236,233,216); color: green; font-weight: bolder; padding-left: 20px} +.listsubsortsubtotal { font-size: 8pt; background-color: rgb(236,233,216); color: green; font-weight: bolder; padding-left: 20px} +.listsortdescription { font-size: 8pt; background-color: rgb(236,233,216); color: black; font-weight: normal; padding-left: 30px} + + .submit { font-family: Verdana, Arial, Helvetica; color: #000000; diff --git a/doc/changelog b/doc/changelog index 032202053..d9d93c08f 100644 --- a/doc/changelog +++ b/doc/changelog @@ -21,6 +21,7 @@ - Ansprechpartner für abweichende Lieferadresse, um das Attribut Geschlecht erweitert - FiBu -> Bericht -> Offene Forderung | Offene Verbindlichkeiten um Altersstrukturliste (30, 60, 90, 120) erweitert - SEPA Hinzufügen von Überweisungen um das Infofeld Fälligkeitsdatum erweitert + - Verkaufsbericht mit Statistiken zu Margen API Änderungen: diff --git a/locale/de/all b/locale/de/all index 97a436685..1affa31e4 100644 --- a/locale/de/all +++ b/locale/de/all @@ -595,6 +595,7 @@ $self->{texts} = { 'EAN-Code' => 'EAN-Code', 'EB-Wert' => 'EB-Wert', 'EK' => 'EK', + 'EK-Preis' => 'Purchase price', 'ELSE' => 'Zusatz', 'ELSTER Export (Taxbird)' => 'ELSTER-Export nach Taxbird', 'ELSTER Export (Winston)' => 'ELSTER Export nach Winston', @@ -792,6 +793,7 @@ $self->{texts} = { 'Hardcopy' => 'Seite drucken', 'Has serial number' => 'Hat eine Serienummer', 'Header' => 'Überschrift', + 'Headers' => 'Überschriften', 'Heading' => 'Überschrift', 'Help' => 'Hilfe', 'Help Template Variables' => 'Hilfe zu Dokumenten-Variablen', @@ -976,6 +978,7 @@ $self->{texts} = { 'MAILED' => 'Gesendet', 'MSG_BROWSER_DOES_NOT_SUPPORT_IFRAMES' => 'Ihr Browser kann leider keine eingebetteten Frames anzeigen. Bitte wählen Sie ein anderes Menü in der Benutzerkonfiguration im Administrationsmenü aus.', 'Main Preferences' => 'Grundeinstellungen', + 'Main sorting' => 'Hauptsortierung', 'Make' => 'Lieferant', 'Manage Custom Variables' => 'Benutzerdefinierte Variablen', 'Manage license keys' => 'Lizenzschlüssel verwalten', @@ -983,6 +986,8 @@ $self->{texts} = { 'Mandatory Departments' => 'Benutzer muss Abteilungen vergeben', 'Mar' => 'März', 'March' => 'März', + 'Margepercent' => 'Ertrag prozentual', + 'Margetotal' => 'Ertrag', 'Margins' => 'Seitenränder', 'Mark as closed' => 'Abschließen', 'Mark as paid?' => 'Als bezahlt markieren?', @@ -1285,6 +1290,9 @@ $self->{texts} = { 'Purchase Prices' => 'Einkaufspreise', 'Purchase delivery order' => 'Lieferschein (Einkauf)', 'Purchase invoices' => 'Einkaufsrechnungen', + 'Purchase net amount' => 'EK-Betrag', + 'Purchase price' => 'EK-Preis', + 'Purchase price total' => 'EK-Betrag', 'Purpose' => 'Verwendungszweck', 'Qty' => 'Menge', 'Qty according to delivery order' => 'Menge laut Lieferschein', @@ -1374,10 +1382,16 @@ $self->{texts} = { 'Sales Invoices' => 'Kundenrechnung', 'Sales Order' => 'Kundenauftrag', 'Sales Orders' => 'Aufträge', + 'Sales Report' => 'Verkaufsbericht', 'Sales and purchase invoices with inventory transactions with taxkeys' => 'Einkaufs- und Verkaufsrechnungen mit Warenbestandsbuchungen mit Steuerschlüsseln', 'Sales delivery order' => 'Lieferschein (Verkauf)', 'Sales invoice number' => 'Ausgangsrechnungsnummer', 'Sales invoices' => 'Verkaufsrechnungen', + 'Sales margin' => 'Marge', + 'Sales margin %' => 'Marge prozentual', + 'Sales net amount' => 'VK-Betrag', + 'Sales price' => 'VK-Preis', + 'Sales price total' => 'VK-Betrag', 'Sales quotation' => 'Angebot', 'Salesman' => 'Verkäufer/in', 'Salesperson' => 'Verkäufer', @@ -1951,6 +1965,7 @@ $self->{texts} = { 'debug' => 'Debug', 'delete' => 'Löschen', 'deliverydate' => 'Lieferdatum', + 'description' => 'Beschreibung', 'direct debit' => 'Lastschrift', 'disposed' => 'Entsorgung', 'done' => 'erledigt', @@ -2026,6 +2041,7 @@ $self->{texts} = { 'sales_order' => 'Kundenauftrag', 'sales_order_list' => 'auftragsliste', 'sales_quotation' => 'Verkaufsangebot', + 'sales_report' => 'verkaufsbericht', 'saved' => 'gespeichert', 'saved!' => 'gespeichert', 'sent' => 'gesendet', diff --git a/menu.ini b/menu.ini index cf9593808..ffb523f80 100644 --- a/menu.ini +++ b/menu.ini @@ -159,6 +159,12 @@ module=ar.pl action=search nextsub=ar_transactions +[AR--Reports--Sales Report] +ACCESS=invoice_edit +module=vk.pl +action=search_invoice +nextsub=invoice_transactions + [AR--Reports--Dunnings] ACCESS=dunning_edit module=dn.pl diff --git a/templates/webpages/vk/search_invoice.html b/templates/webpages/vk/search_invoice.html new file mode 100644 index 000000000..18ff0fed4 --- /dev/null +++ b/templates/webpages/vk/search_invoice.html @@ -0,0 +1,173 @@ +[%- USE T8 %] + + +
+ + + + + + + + + + + + + +
[% title %]
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
[% 'Main sorting' | $T8 %] + + + + +
[% 'Customer' | $T8 %] + [%- INCLUDE 'generic/multibox.html' + name = 'customer', + default = oldcustomer, + style = 'width: 250px', + DATA = ALL_VC, + id_sub = 'vc_keys', + label_key = 'name', + select = vc_select, + limit = vclimit, + show_empty = 1, + allow_textbox = 1, + -%] +
[% 'Department' | $T8 %] + [%- INCLUDE 'generic/multibox.html' + name = 'department', + style = 'width: 250px', + DATA = ALL_DEPARTMENTS, + id_key = 'id', + label_key = 'description', + show_empty = 1, + allow_textbox = 0, + -%] +
[% 'Project Number' | $T8 %] + [%- INCLUDE 'generic/multibox.html' + name = 'project_id', + style = "width: 250px", + DATA = ALL_PROJECTS, + id_key = 'id', + label_key = 'projectnumber', + limit = vclimit, + show_empty = 1, + allow_textbox = 0, + -%] +
[% 'Part Number' | $T8 %]
[% 'Part Description' | $T8 %]
[% 'From' | $T8 %] + + + [% 'Bis' | $T8 %] + + +
+
+ + + + + +
[% 'Include in Report' | $T8 %] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
[% 'Description' | $T8 %][% 'Part Number' | $T8 %][% 'Invnumber' | $T8 %][% 'Invdate' | $T8 %]
[% 'Quantity' | $T8 %][% 'Discount' | $T8 %][% 'Unit' | $T8 %]
[% 'Sales price' | $T8 %][% 'Sales price total' | $T8 %][% 'Purchase price' | $T8 %][% 'Purchase price total' | $T8 %]
[% 'Margetotal' | $T8 %][% 'Margepercent' | $T8 %]
[% 'Subtotal' | $T8 %][% 'Total' | $T8 %][% 'Headers' | $T8 %]
[% 'Decimalplaces' | $T8 %]
+
+

+ +
+ +
+ + + diff --git a/vk.pl b/vk.pl new file mode 120000 index 000000000..385000d1b --- /dev/null +++ b/vk.pl @@ -0,0 +1 @@ +am.pl \ No newline at end of file -- 2.20.1