From 28999c3cbfe038561cb0c418a44a29ae689ad050 Mon Sep 17 00:00:00 2001 From: Werner Hahn Date: Thu, 4 Apr 2024 09:29:40 +0200 Subject: [PATCH] POS: initial --- SL/Controller/Order.pm | 34 +- SL/Controller/POS.pm | 97 ++ css/design40/less/pos.less | 56 + css/design40/less/style.less | 1 + .../manual/form-elements-special.html | 8 +- css/design40/style.css | 2 +- js/kivi.POS.js | 46 + js/kivi.Poso.js | 1023 +++++++++++++++++ menus/user/90-pos.yaml | 7 + ..._order_item_row_point_of_sales_dialog.html | 37 + templates/design40_webpages/pos/form.html | 353 ++++++ .../pos/tabs/_item_input.html | 34 + .../design40_webpages/pos/tabs/_row.html | 46 + 13 files changed, 1725 insertions(+), 19 deletions(-) create mode 100644 SL/Controller/POS.pm create mode 100644 css/design40/less/pos.less create mode 100644 js/kivi.POS.js create mode 100644 js/kivi.Poso.js create mode 100644 menus/user/90-pos.yaml create mode 100644 templates/design40_webpages/pos/_edit_order_item_row_point_of_sales_dialog.html create mode 100644 templates/design40_webpages/pos/form.html create mode 100644 templates/design40_webpages/pos/tabs/_item_input.html create mode 100644 templates/design40_webpages/pos/tabs/_row.html diff --git a/SL/Controller/Order.pm b/SL/Controller/Order.pm index 949ddc71fa..c71842e933 100644 --- a/SL/Controller/Order.pm +++ b/SL/Controller/Order.pm @@ -1039,6 +1039,9 @@ sub action_update_item_input_row { # add an item row for a new item entered in the input row sub action_add_item { my ($self) = @_; + my $template_name = $::form->{point_of_sale} ? + 'pos/tabs/_row' + : 'order/tabs/_row'; delete $::form->{add_item}->{create_part_type}; @@ -1055,10 +1058,12 @@ sub action_add_item { $self->get_item_cvpartnumber($item); my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000); - my $row_as_html = $self->p->render('order/tabs/_row', - ITEM => $item, - ID => $item_id, - SELF => $self, + + my $row_as_html = $self->p->render( + $template_name, + ITEM => $item, + ID => $item_id, + SELF => $self, ); if ($::form->{insert_before_item_id}) { @@ -1070,13 +1075,13 @@ sub action_add_item { } if ( $item->part->is_assortment ) { - $form_attr->{qty_as_number} = 1 unless $form_attr->{qty_as_number}; foreach my $assortment_item ( @{$item->part->assortment_items} ) { - my $attr = { parts_id => $assortment_item->parts_id, - qty => $assortment_item->qty * $::form->parse_amount(\%::myconfig, $form_attr->{qty_as_number}), # TODO $form_attr->{unit} - unit => $assortment_item->unit, - description => $assortment_item->part->description, - }; + my $attr = { + parts_id => $assortment_item->parts_id, + qty => $assortment_item->qty * ($item->qty || 1), # TODO $item->unit + unit => $assortment_item->unit, + description => $assortment_item->part->description, + }; my $item = new_item($self->order, $attr); # set discount to 100% if item isn't supposed to be charged, overwriting any customer discount @@ -1086,10 +1091,11 @@ sub action_add_item { $self->recalc(); $self->get_item_cvpartnumber($item); my $item_id = join('_', 'new', Time::HiRes::gettimeofday(), int rand 1000000000000); - my $row_as_html = $self->p->render('order/tabs/_row', - ITEM => $item, - ID => $item_id, - SELF => $self, + my $row_as_html = $self->p->render( + $template_name, + ITEM => $item, + ID => $item_id, + SELF => $self, ); if ($::form->{insert_before_item_id}) { $self->js diff --git a/SL/Controller/POS.pm b/SL/Controller/POS.pm new file mode 100644 index 0000000000..4a144a6580 --- /dev/null +++ b/SL/Controller/POS.pm @@ -0,0 +1,97 @@ +package SL::Controller::POS; + +use strict; +use parent qw(SL::Controller::Base); + +use SL::Controller::Order; + +use SL::Model::Record; +use SL::DB::ValidityToken; +use SL::DB::Order::TypeData qw(:types); + +use SL::Locale::String qw(t8); + +use Rose::Object::MakeMethods::Generic +( + 'scalar --get_set_init' => [ qw( + order_controller order + ) ] +); + +# add a new point of sales order +# it's a sales order with a diffrent form +sub action_add { + my ($self) = @_; + $::form->{type} = SALES_ORDER_TYPE(); + + $self->order(SL::Model::Record->update_after_new($self->order)); + + $self->order_controller->pre_render(); + $self->pre_render(); + + if (!$::form->{form_validity_token}) { + $::form->{form_validity_token} = SL::DB::ValidityToken->create(scope => SL::DB::ValidityToken::SCOPE_ORDER_SAVE())->token; + } + + $self->render( + 'pos/form', + title => t8('Point of Sales'), + %{$self->{template_args}} + ); +} + +sub action_edit_order_item_row_point_of_sales_dialog { + my ($self) = @_; + + my $item; + my $temp_item_id = $::form->{item_id}; + foreach my $idx (0 .. (scalar @{$::form->{orderitem_ids}} - 1)) { + if ($::form->{orderitem_ids}->[$idx] eq $temp_item_id) { + $item = $self->order->items->[$idx]; + last; + } + } + die "cound not find item with item with id $temp_item_id" unless $item; + + $self->render( + 'pos/_edit_order_item_row_point_of_sales_dialog', { layout => 0 }, + popup_dialog => 1, + popup_js_delete_row_function => "kivi.POS.delete_order_item_row_point_of_sales('$temp_item_id')", + popup_js_close_function => '$("#edit_order_item_row_point_of_sales_dialog").dialog("close")', + popup_js_assign_function => "kivi.POS.assign_edit_order_item_row_point_of_sales('$temp_item_id')", + ITEM => $item + ); +} + +# +# helpers +# + +sub pre_render { + my ($self) = @_; + + $::request->{layout}->use_javascript("${_}.js") for qw( + kivi.POS + ); + + # remove actionbar from order_controller + for my $bar ($::request->layout->get('actionbar')) { + $bar->actions([]); + } +} + +sub order { + my $self = shift @_; + $self->order_controller->order(@_); +} + +# +# intits +# + +sub init_order_controller { + my ($self) = @_; + SL::Controller::Order->new(); +} + +1; diff --git a/css/design40/less/pos.less b/css/design40/less/pos.less new file mode 100644 index 0000000000..53c91004a4 --- /dev/null +++ b/css/design40/less/pos.less @@ -0,0 +1,56 @@ +/* ------------------------------------------------------------- */ +/* POS (pos.less) */ +/* ------------------------------------------------------------- */ + + + +// ------------------------------------------------------------ +// General page layout +// ------------------------------------------------------------ + +.pos_wrapper{ + border: solid blue; + position: relative; + height: 85vh; +} + +// pos_content + +.pos_content{ + margin-right: 600px; + border: thin solid red; +} + +// left_content + +.left_input{ + float:left; + padding-right: 3em; +} + +// buttons + +.buttons{ + position: absolute; + right: 0px; + top: 0px; + + width: 600px; + border: thin solid green; +} + +.container_pos_left{ + display: grid; + grid-template-columns: 1fr 1fr; + column-gap: 10px; + row-gap: 15px; +} + +.pos_button{ + height: 50px; + border: solid green !important; + text-align: center; + line-height: 50px; + padding: 0 !important; + display: inline-block; +} diff --git a/css/design40/less/style.less b/css/design40/less/style.less index c23ea1d6ef..96624a192c 100755 --- a/css/design40/less/style.less +++ b/css/design40/less/style.less @@ -106,6 +106,7 @@ // ----------------------- @import 'requirement_spec.less'; // @import 'specials.less'; +@import 'pos.less'; diff --git a/css/design40/manual/form-elements-special.html b/css/design40/manual/form-elements-special.html index 70b9fd8e9c..ac2f449b0f 100644 --- a/css/design40/manual/form-elements-special.html +++ b/css/design40/manual/form-elements-special.html @@ -63,7 +63,7 @@

ms2side (.ms2side / MultiSelect2Side)

Alle verfügbaren Elemente
- @@ -201,10 +201,10 @@

Benutzerdefinierte Variablen