Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 19e2bb1a

Von Tamino Steinert vor etwa 1 Jahr hinzugefügt

  • ID 19e2bb1a553ce7459e8030343d810e424593f08b
  • Vorgänger 3926714c
  • Nachfolger 66376ef2

EmailJournal: Workflow: Vorschlag der passenden Belege

Unterschiede anzeigen:

SL/Controller/EmailJournal.pm
use SL::DB::Employee;
use SL::DB::EmailJournal;
use SL::DB::EmailJournalAttachment;
use SL::Presenter::EmailJournal;
use SL::Presenter::Tag qw(html_tag div_tag radio_button_tag);
use SL::Helper::Flash;
use SL::Locale::String qw(t8);
use SL::System::TaskServer;
use SL::Presenter::EmailJournal;
use SL::DB::Order;
use SL::DB::Order::TypeData;
......
use SL::DB::Manager::Customer;
use SL::DB::Manager::Vendor;
use List::MoreUtils qw(any);
use Rose::Object::MakeMethods::Generic
(
scalar => [ qw(entry) ],
......
my %RECORD_TYPES_INFO = (
Order => {
controller => 'Order',
model => 'SL::DB::Order',
class => 'Order',
types => SL::DB::Order::TypeData->valid_types(),
},
DeliveryOrder => {
controller => 'DeliveryOrder',
model => 'SL::DB::DeliveryOrder',
class => 'DeliveryOrder',
types => SL::DB::DeliveryOrder::TypeData->valid_types(),
},
Reclamation => {
controller => 'Reclamation',
model => 'SL::DB::Reclamation',
class => 'Reclamation',
types => SL::DB::Reclamation::TypeData->valid_types(),
},
ArTransaction => {
controller => 'ar.pl',
model => 'SL::DB::Invoice',
class => 'Invoice',
types => [
'ar_transaction',
],
},
Invoice => {
controller => 'is.pl',
model => 'SL::DB::Invoice',
class => 'Invoice',
types => [
'invoice',
'invoice_for_advance_payment',
......
},
ApTransaction => {
controller => 'ap.pl',
model => 'SL::DB::PurchaseInvoice',
class => 'PurchaseInvoice',
types => [
'ap_transaction',
],
},
PurchaseInvoice => {
controller => 'ir.pl',
model => 'SL::DB::PurchaseInvoice',
class => 'PurchaseInvoice',
types => [
'purchase_invoice',
'purchase_credit_note',
......
} keys %RECORD_TYPES_INFO;
my %RECORD_TYPE_TO_MODEL =
map {
my $model = $RECORD_TYPES_INFO{$_}->{model};
map { $_ => $model } @{ $RECORD_TYPES_INFO{$_}->{types} }
my $class = $RECORD_TYPES_INFO{$_}->{class};
map { $_ => "SL::DB::$class" } @{ $RECORD_TYPES_INFO{$_}->{types} }
} keys %RECORD_TYPES_INFO;
my %RECORD_TYPE_TO_MANAGER =
map {
my $class = $RECORD_TYPES_INFO{$_}->{class};
map { $_ => "SL::DB::Manager::$class" } @{ $RECORD_TYPES_INFO{$_}->{types} }
} keys %RECORD_TYPES_INFO;
my @ALL_RECORD_TYPES = map { @{ $RECORD_TYPES_INFO{$_}->{types} } } keys %RECORD_TYPES_INFO;
# has do be done at runtime for translation to work
sub get_record_types_with_info {
# TODO: what record types can be created, which are only available in workflows?
my @record_types_with_info = ();
for my $record_class ('SL::DB::Order', 'SL::DB::DeliveryOrder', 'SL::DB::Reclamation') {
my $valid_types = "${record_class}::TypeData"->valid_types();
for my $type (@$valid_types) {
my $type_data = SL::DB::Helper::TypeDataProxy->new($record_class, $type);
push @record_types_with_info, {
record_type => $type,
customervendor => $type_data->properties('customervendor'),
text => $type_data->text('type'),
};
}
}
push @record_types_with_info, (
# invoice
{ record_type => 'invoice', customervendor => 'customer', text => t8('Invoice') },
{ record_type => 'invoice_for_advance_payment', customervendor => 'customer', text => t8('Invoice for Advance Payment')},
{ record_type => 'invoice_for_advance_payment_storno', customervendor => 'customer', text => t8('Storno Invoice for Advance Payment')},
{ record_type => 'final_invoice', customervendor => 'customer', text => t8('Final Invoice')},
{ record_type => 'invoice_storno', customervendor => 'customer', text => t8('Storno Invoice')},
{ record_type => 'credit_note', customervendor => 'customer', text => t8('Credit Note')},
{ record_type => 'credit_note_storno', customervendor => 'customer', text => t8('Storno Credit Note')},
{ record_type => 'ar_transaction', customervendor => 'customer', text => t8('AR Transaction')},
# purchase invoice
{ record_type => 'purchase_invoice', customervendor => 'vendor', text => t8('Purchase Invoice')},
{ record_type => 'purchase_credit_note', customervendor => 'vendor', text => t8('Purchase Credit Note')},
{ record_type => 'ap_transaction', customervendor => 'vendor', text => t8('AP Transaction')},
);
return @record_types_with_info;
}
sub record_types_for_customer_vendor_type {
my ($self, $customer_vendor_type) = @_;
return [ map { $_->{record_type} } grep { $_->{customervendor} eq $customer_vendor_type } $self->get_record_types_with_info ];
}
#
# actions
......
$::form->error(t8('You do not have permission to access this entry.'));
}
# TODO: what record types can be created, which are only available in workflows?
my @record_types_with_info = ();
for my $record_class ('SL::DB::Order', 'SL::DB::DeliveryOrder', 'SL::DB::Reclamation') {
my $valid_types = "${record_class}::TypeData"->valid_types();
for my $type (@$valid_types) {
my $type_data = SL::DB::Helper::TypeDataProxy->new($record_class, $type);
push @record_types_with_info, {
record_type => $type,
customervendor => $type_data->properties('customervendor'),
text => $type_data->text('type'),
};
}
}
push @record_types_with_info, (
# invoice
{ record_type => 'ar_transaction' , customervendor => 'customer', text => t8('AR Transaction')},
{ record_type => 'invoice' , customervendor => 'customer', text => t8('Invoice') },
{ record_type => 'invoice_for_advance_payment' , customervendor => 'customer', text => t8('Invoice for Advance Payment')},
{ record_type => 'invoice_for_advance_payment_storno', customervendor => 'customer', text => t8('Storno Invoice for Advance Payment')},
{ record_type => 'final_invoice' , customervendor => 'customer', text => t8('Final Invoice')},
{ record_type => 'invoice_storno' , customervendor => 'customer', text => t8('Storno Invoice')},
{ record_type => 'credit_note' , customervendor => 'customer', text => t8('Credit Note')},
{ record_type => 'credit_note_storno' , customervendor => 'customer', text => t8('Storno Credit Note')},
# purchase invoice
{ record_type => 'ap_transaction' , customervendor => 'vendor', text => t8('AP Transaction')},
{ record_type => 'purchase_invoice' , customervendor => 'vendor', text => t8('Purchase Invoice')},
{ record_type => 'purchase_credit_note', customervendor => 'vendor', text => t8('Purchase Credit Note')},
);
my @record_types_with_info = $self->get_record_types_with_info();
my $customer_vendor = $self->find_customer_vendor_from_email($self->entry);
my $cv_type = $customer_vendor && $customer_vendor->is_vendor ? 'vendor' : 'customer';
my $record_types = $self->record_types_for_customer_vendor_type($cv_type);
my @records = $self->get_records_for_types(
$record_types,
customer_vendor_type => $cv_type,
customer_vendor_id => $customer_vendor && $customer_vendor->id,
with_closed => 0,
);
$self->setup_show_action_bar;
$self->render(
......
CUSTOMER_VENDOR => , $customer_vendor,
CV_TYPE_FOUND => $customer_vendor && $customer_vendor->is_vendor ? 'vendor' : 'customer',
RECORD_TYPES_WITH_INFO => \@record_types_with_info,
RECORDS => \@records,
back_to => $back_to
);
}
sub get_records_for_types {
my ($self, $record_types, %params) = @_;
$record_types = [ $record_types ] unless ref $record_types eq 'ARRAY';
my $cv_type = $params{customer_vendor_type};
my $cv_id = $params{customer_vendor_id};
my $with_closed = $params{with_closed};
my @records = ();
foreach my $record_type (@$record_types) {
my $manager = $RECORD_TYPE_TO_MANAGER{$record_type};
my $model = $RECORD_TYPE_TO_MODEL{$record_type};
my %additional_where = ();
if ($cv_type && $cv_id) {
$additional_where{"${cv_type}_id"} = $cv_id;
}
unless ($with_closed) {
if (any {$_ eq 'closed' } $model->meta->columns) {
$additional_where{closed} = 0;
} elsif (any {$_ eq 'paid' } $model->meta->columns) {
$additional_where{amount} = { gt => \'paid' };
}
}
my $records_of_type = $manager->get_all(
where => [
$manager->type_filter($record_type),
%additional_where,
],
);
push @records, @$records_of_type;
}
return @records;
}
sub action_attachment_preview {
my ($self) = @_;
......
my $customer_vendor = $::form->{customer_vendor_selection};
my $customer_vendor_id = $::form->{"${customer_vendor}_id"};
my $action = $::form->{action_selection};
my $record_type = $::form->{"${customer_vendor}_record_type_selection"};
my $record_id = $::form->{"${record_type}_id"};
my $record_type_id = $::form->{"record_type_id"};
die t8("No record is selected.") unless $record_type_id || $action eq 'create_new';
die "no 'email_journal_id' was given" unless $email_journal_id;
die "no 'customer_vendor_selection' was given" unless $customer_vendor;
die "no 'action_selection' was given" unless $action;
my ($record_type, $record_id) = split(/-/, $record_type_id);
if ($action eq 'linking') {
return $self->link_and_add_attachment_to_record({
......
->render();
}
sub action_update_record_list {
my ($self) = @_;
$::auth->assert('email_journal');
my $customer_vendor_type = $::form->{customer_vendor_selection};
my $customer_vendor_id = $::form->{"${customer_vendor_type}_id"};
my $record_type = $::form->{"${customer_vendor_type}_record_type_selection"};
my $with_closed = $::form->{with_closed};
$record_type ||= $self->record_types_for_customer_vendor_type($customer_vendor_type);
my @records = $self->get_records_for_types(
$record_type,
customer_vendor_type => $customer_vendor_type,
customer_vendor_id => $customer_vendor_id,
with_closed => $with_closed,
);
unless (@records) {
$self->js->replaceWith('#record_list', div_tag(
html_tag('h3', t8('No records found.')),
id => 'record_list',
))->render();
return;
}
my $new_div = div_tag(
join('', map {
div_tag(
radio_button_tag('record_type_id',
value => $_->record_type . "-" . $_->id, label => $_->displayable_name,
class => "record_radio", label_class => "record_radio",
),
id => "record_$_->{id}",
)
} @records),
id => 'record_list',
);
$self->js->replaceWith('#record_list', $new_div)->render();
}
#
# filters
#
css/design40/email_journal.css
/* E-Mail-Journal */
.email_journal_details tbody pre {
margin: 0px;
input.record_radio {
visibility:hidden;
position:absolute;
float: left;
}
.email_journal_details tbody th {
text-align: right;
vertical-align: top;
label.record_radio {
cursor: pointer;
float: left;
overflow: hidden;
width: 200px;
padding: 5px;
margin: 5px;
border-radius: 5px;
border: 1px solid;
text-align: center;
}
.email_journal_details tbody td {
vertical-align: top;
input.record_radio:checked + label {
background-color: var(--color-lighter);
}
js/kivi.EmailJournal.js
$('#vendor_div').show();
$('#vendor_record_types_div').show();
}
kivi.EmailJournal.update_record_type_selection(customer_vendor);
kivi.EmailJournal.update_record_list();
}
ns.update_action_selection = function() {
let record_action = $('#action_selection').val();
$('#record_type_div').hide();
$('#no_record_type_div').hide();
$('#record_div').hide();
$('#no_record_div').hide();
if (record_action == 'create_new') {
$('#no_record_type_div').show();
$('#no_record_div').show();
} else {
$('#record_type_div').show();
$('#record_div').show();
}
}
ns.update_record_type_selection = function(customer_vendor) {
let record_type = $('#' + customer_vendor + '_record_type_selection').val();
ns.update_record_list = function() {
let $form = $('#record_action_form');
$('.record_type').hide();
if (record_type != '') {
$('#' + record_type + '_div').show();
} else {
$('#record_type_placeholder_div').show();
}
let data = $form.serializeArray();
data.push({ name: 'action', value: 'EmailJournal/update_record_list' });
$.post("controller.pl", data, kivi.eval_json_result);
}
ns.apply_action_with_attachment = function() {
templates/design40_webpages/email_journal/show.html
cv_type _ "_id",
CUSTOMER_VENDOR.is_customer == cv_is_cusotmer ? CUSTOMER_VENDOR : undef,
type=cv_type, class="wi-normal", placeholder=LxERP.t8(cv_name)
onchange='kivi.EmailJournal.update_record_list();'
) %]
</div>
[% END %]
......
value_key='value', title_key='name',
with_empty=1, empty_value='', empty_title=LxERP.t8("Select record type"),
class="wi-normal",
onchange='kivi.EmailJournal.update_record_type_selection("' _ customer_vendor _ '");'
onchange='kivi.EmailJournal.update_record_list();'
) %]
</div>
[% END %]
<div id="record_type_div" class="col" style="display:block">
[% FOREACH record_info = RECORD_TYPES_WITH_INFO %]
<div id="[% record_info.record_type _ "_div" %]" class="col record_type" style="display:none">
[% L.input_tag(record_info.record_type _ "_id", '',
style="color:black", class="wi-normal",
placeholder=record_info.record_type _ " id") %]
</div>
[% END %]
<div id="record_type_placeholder_div" class="col record_type" style="display:block">
[% L.input_tag('cv_placeholder', '',
style="color:black", class="wi-normal", disabled=1,
placeholder=LxERP.t8("Select record type first"),
) %]
</div>
</div>
<div id="no_record_type_div" class="col" style="display:none">
[% L.input_tag('cv_placeholder', '',
style="color:black", class="wi-normal", disabled=1,
placeholder=LxERP.t8("No record needed"),
) %]
<div id="with_closed_div" class="col">
[% L.select_tag('with_closed',
[
{value => "1", name => LxERP.t8("With closed")},
{value => "0", name => LxERP.t8("Only open")},
],
default = 0, value_key='value', title_key='name',
class="wi-small",
onchange='kivi.EmailJournal.update_record_list();'
) %]
</div>
<div class="col">
[% L.button_tag('kivi.EmailJournal.apply_action_with_attachment();', LxERP.t8('Apply with Attachment')) %]
</div>
</div> <!-- action_div -->
[% BLOCK panel_1 %]
<div id="record_div">
<div id="record_list">
[% FOREACH record = RECORDS %]
<div id="record_[% record.id %]">
[% L.radio_button_tag('record_type_id', class="record_radio",
value=record.record_type _ '-' _ record.id,
label_class="record_radio", label=record.displayable_name) %]
</div>
[% END %]
[% IF RECORDS.size == 0 %]
<div id="no_record_div">
<h3> [% LxERP.t8("No records found.") %] </h3>
</div>
[% END %]
</div>
</div>
<div id="no_record_div" class="col" style="display:none">
<h3> [% LxERP.t8("No record needed.") %] </h3>
</div>
[% END %]
[% SET display_status = (RECORDS.size > 20 ? 'closed' : 'open');
INCLUDE 'common/toggle_panel.html'
block_name='panel_1'
button_closed = LxERP.t8('Show Records')
button_open = LxERP.t8('Hide Records')
;
%]
</form>
<!-- kivi.EmailJournal.update_attachment_preview -->

Auch abrufbar als: Unified diff